C++ 상속자/ 파생클래스에서 베이스클래스 복사생성자 생성 질문 드립니다..

sungsoo1214의 이미지

복사 생성자를 베이스클래스와 파생클래스에서 각각 만들었는데, 만들고도 이해가 되지 않는 부분이 있어 질문 드립니다.

Customer가 base 클래스이고, PriorityCustomer가 파생 클래스 입니다. 그래서 Customer class 내부에서 복사생성자를 만들었고,
PriorrityCustomer안에서도 복사 생성자를 만들었습니다.

** PriorityCustomer(const PriorityCustomer& p):Customer(p) **

이렇게 만들었는데,, 사실 되긴 했지만, 이해가 가질 않습니다. 그러니깐 Customer(const Customer& c) 형식이고, 대입되는 자료형이 Customer 입니다.

하지만 p는 자료형이 PriortyCustomer입니다. 근데 어떻게 복사생성이 일어나는지 이해가 안됩니다.

class Customer{
    char* name;
public:
    Customer():name(0){}
    Customer(char * _name)
    {
        name=new char[strlen(_name)+1];
        strcpy(name, _name);
    }
    Customer(const Customer& c)
    {
        name=new char[strlen(c.name)+1];
        strcpy(name,c.name);
    }
    ~Customer(){delete []name;}
    const char* getname(){return name;};
};
 
class PriorityCustomer : public Customer{
    int priority;
public:
    PriorityCustomer():priority(0){}
    PriorityCustomer(char *_name, int pri=0):Customer(_name), priority(pri){}
    PriorityCustomer(const PriorityCustomer& p):Customer(p),priority(p.priority)
    {
 
    }
    ~PriorityCustomer(){}
    const int getpriority(){return priority;}
    void Print()
    {
        cout<<getname()<<" "<<getpriority()<<endl;
    }
};

hano881112의 이미지

C++의 다형성이 작용한 결과입니다.
다형성은 부모 / 자식의 관계를 가지고 있는 클래스 간에는 부모 클래스의 인터페이스를 공유하여 사용할 수 있는 개념인데요, 혹여 알고 계신 개념이시라도 조금 더 알아보시는 편이 좋을 거 같아요.

PriorityCustomer pc("name", 1);
Customer c(pc);

이 코드의 아래, 'Customer c(pc);' 는 PriorityCustomer 클래스 객체가 Customer 객체로 다형성을 통해 형변환이 되는데요.
그래서 Customer 복사 생성자에서는 PriorityCustomer 객체의 참조자를 받았어도 그 객체에서 Customer 클래스의 인터페이스밖에 제공받지 못합니다.
(그러니까 PriorityCustomer 객체가 Customer인 척 하는 거에요.)
즉, getname() 인터페이스로 "name" 문자열은 받아올 수 있지만, getpriority()를 통해 1은 받아올 수 없습니다.

(만약 매개변수를 참조자(&)로 받지 않았다면 그 매개변수에는 PriorityCustomer 객체 내에서 Customer 클래스에 해당하는 데이터만 받아와 복사됩니다. 즉, 그 블록 내부에서 해당 데이터를 다시 PriorityCustomer 클래스로 활용하고 싶어도 데이터가 잘려나가서 사용할 수 없습니다.)

아무튼 다형성 쪽을 조금 더 알아보시면 될 것 같습니다. 설명이 너무 중구난방이네요; 죄송합니다 ㅎㅎ;

sungsoo1214의 이미지

제가 푼 문제가 C++ 책에서 다형성을 배우기 전에 상속 파트에서 풀어보라는 예제였습니다.

다형성부분을 공부해봐야겠네요.. 답글 감사합니다 ^^

gilgil의 이미지

is-a(PriorityCustomer is a Customer) 관계가 형성되어 있는 것을 가지고 type casting으로 본다는 건 좀 아닌 것 같은데요?

hano881112의 이미지

답글과 지적 감사합니다-

부모 자식간의 is-a 관계에 대해서 언급하지 않은 것은 확실히 부족한 설명이라고 보입니다.. ㅎㅎ

제가 언급했던 형변환은

Customer(const Customer& c)
{
     name=new char[strlen(c.name)+1];
     strcpy(name,c.name);
}

이 복사 생성자를 통하여 PriorityCustomer 객체가 복사되어 Customer 객체가 생성되는 과정에서 PriorityCustomer 객체가 Customer 형으로 형변환 됨을 언급했던 것입니다.

shint의 이미지

PriorityCustomer(const PriorityCustomer& p):Customer(p) - 생성자 변수 초기화' (묵시적 형변환)

제가 알기로는
명시적 형변환'은 사용자가 코드로 적어주는거고.
묵시적 형변환'은 컴파일러가 자동으로 형변환을 해줍니다.

포인터와 주소는 4바이트 = 4바이트;

//물론. 형변환을 하더라도. 변수 크기가 다르면. 데이터가 잘못되겠죠. ㅇ_ㅇ;;
int a; //4바이트
double b; //8바이트

//묵시적 형변환
a = b;
b = a;

//명시적 형변환
a = (int)b;
b = (double)a;

#include <cstdlib>
#include <iostream>
 
using namespace std;
 
 
class Customer{
private:
    char* name;
public:
 
    Customer():name(0){}
    Customer(char * _name)
    {
        name=new char[strlen(_name)+1];
        strcpy(name, _name);
        printf("1 _name:%s\n", _name);
    }
    Customer(const Customer& c)
    {
        name=new char[strlen(c.name)+1];
        strcpy(name,c.name);
        printf("2 Customers:%x\n",&c);
        printf("this: %x\n", this);
    }
    ~Customer(){delete []name;}
    const char* getname(){return name;};
};
 
class PriorityCustomer : public Customer{
private:
    int priority;
public:
 
    PriorityCustomer():priority(0){}
    PriorityCustomer(char *_name, int pri=0):Customer(_name), priority(pri)
    {
        printf("3 _name\n", _name);
        printf("this: %x\n", this);
    }
 
    //                                        : 생성자 변수 초기화' (묵시적 형변환) - Customer(p)
    PriorityCustomer(const PriorityCustomer& p):Customer(p),priority(p.priority)
    {
        printf("4 PriorityCustomer:%x\n", &p);
        printf("this: %x\n", this);
    }
    ~PriorityCustomer(){}
    const int getpriority(){return priority;}
    void Print()
    {
        cout < < getname() < < " " < < getpriority() < < endl;
    }
};
 
 
int main(int argc, char *argv[])
{
    PriorityCustomer prc("test", 1);
    Customer c(prc);
 
    //
    printf("-------------------\n");
 
    //명시적 형변환
    Customer * pc;
    pc = (Customer*)&prc;
 
 
    system("PAUSE");
    return EXIT_SUCCESS;
}
 
#if 0
1 _name:test
3 _name
this: 22ff50
2 Customers:22ff50
this: 22ff40
-------------------
#endif

----------------------------------------------------------------------------
젊음'은 모든것을 가능하게 만든다.

매일 1억명이 사용하는 프로그램을 함께 만들어보고 싶습니다.
정규 근로 시간을 지키는. 야근 없는 회사와 거래합니다.

각 분야별. 좋은 책'이나 사이트' 블로그' 링크 소개 받습니다. shintx@naver.com

sungsoo1214의 이미지

Priority class가 Customer로 묵시적 형변환 된거군요..

감사합니다 ㅎㅎ

근데 밑에 this : customer this 같은 주소는 무엇인가요??

shint의 이미지

ㅇ_ㅇ;; 제가 틀릴 수 도 있으니까요.
아니면. 네이버. 다음. 구글. 도서관. 서점. 네이버 책. 책 등에서 찾아보거나요.

class 에는 this 포인터가 있다고 합니다. 4바이트 크기에 클래스의 주소일겁니다.
fn(&); 함수에서 클래스가 레퍼런스 참조'되어서 구현되는거니. 묵시적 형변환이라고 하기도 애매하네요. ㅇ_ㅇ;; 정확한건 항상 확인하는것이 좋습니다.

아니면. VC 컴파일러로 어셈블리 코드를 확인해보시면. 정확한 내용을 확인하 실 수 있습니다.
const Customer& c <= Customer(p) <= const PriorityCustomer& p;
const PriorityCustomer& p;
const Customer& c;
c=p;

C++ 생성자초기화 6가지방법, 복사생성자
http://cafe.naver.com/kilius/21

놀라운건. 자식에서 생성자 초기화를 할때. 변수가 아닌 부모에 클래스 생성자로도 가능하다는거네요. 변수만 되는줄 착각.;;
MFC 에서 자주 보던건데도. 생소합니다. ㅇ_ㅇ;;

오버로딩 오버라이딩 (overloading overriding) c++
http://thrillfighter.tistory.com/164

이 글 내용으로 본다면. 오버로딩 된 생성자를 오버라이딩해서. 호출.한다고 하려고 했는데. 같은 이름에 함수는 없으니...
그냥. 자식에서. 인자값이 다양하게 오버로딩 된 부모에 생성자 호출이네요. ㅇ_ㅇ;;

----------------------------------------------------------------------------
젊음'은 모든것을 가능하게 만든다.

매일 1억명이 사용하는 프로그램을 함께 만들어보고 싶습니다.
정규 근로 시간을 지키는. 야근 없는 회사와 거래합니다.

각 분야별. 좋은 책'이나 사이트' 블로그' 링크 소개 받습니다. shintx@naver.com

shint의 이미지

Customer(p) 를 지워도 실행 결과가 똑같네요.
그렇다면. 그냥 변수 초기화만 된게 아닐까 생각됩니다. ㅇ_ㅇ?? 이건 뭔지 모르겠네요??

1 _name:test
3 _name
this: 22ff50
2 Customers:22ff50
this: 22ff40

1 _name:test
3 _name
this: 22ff50
2 Customers:22ff50
this: 22ff40

확인해보니. 호출도 하지 않았네요. ㅇ_ㅇ;;

다시 구현하니. 호출 됩니다. 결국. PriorityCustomer 주소를 계속 사용하게 됩니다.
자식에서 부모의 생성자() 호출이 되었습니다.
그 해당 인자값은 참조된(레퍼런스) 주소를 사용해서 전달 됩니다.
이 포인터 주소를 묵시적형변환을 통해서 사용할 수 있게 됩니다.

#include <cstdlib>
#include <iostream>
 
using namespace std;
 
 
class Customer{
private:
    char* name;
public:
 
    Customer():name(0){}
    Customer(char * _name)
    {
        name=new char[strlen(_name)+1];
        strcpy(name, _name);
        printf("1 _name:%s\n", _name);
        printf("\n");
    }
    Customer(const Customer& c)
    {
        name=new char[strlen(c.name)+1];
        strcpy(name,c.name);
        printf("2 Customers:%x\n",&c);
        printf("2 this: %x\n", this);
        printf("\n");
    }
    ~Customer(){delete []name;}
    const char* getname(){return name;};
public:
    void pr(int n)
    {
        printf("xxxxx\n");
    }
};
 
class PriorityCustomer : public Customer{
private:
    int priority;
public:
 
    PriorityCustomer():priority(0){}
    PriorityCustomer(char *_name, int pri=0):Customer(_name), priority(pri)
    {
        printf("3 _name\n", _name);
        printf("3 this: %x\n", this);
        printf("\n");
    }
    PriorityCustomer(const PriorityCustomer& p):Customer(p),priority(p.priority)
    {
        printf("4 PriorityCustomer:%x\n", &p);
        printf("4 this: %x\n", this);
        printf("\n");
    }
    ~PriorityCustomer(){}
    const int getpriority(){return priority;}
    void Print()
    {
        cout<<getname()<<" "<<getpriority()<<endl;
    }
};
 
 
 
int main(int argc, char *argv[])
{
    PriorityCustomer prc("test", 1);
    Customer c(prc);
    PriorityCustomer prc2(prc);
 
    //
    printf("-------------------\n");
 
    //
    Customer * pc;
    pc = (Customer*)&prc;
 
 
    system("PAUSE");
    return EXIT_SUCCESS;
}
 
 
#if 0
1 _name:test
 
3 _name
3 this: 22ff50
 
2 Customers:22ff50
2 this: 22ff40
 
2 Customers:22ff50
2 this: 22ff30
 
4 PriorityCustomer:22ff50
4 this: 22ff30
#endif

----------------------------------------------------------------------------
젊음'은 모든것을 가능하게 만든다.

매일 1억명이 사용하는 프로그램을 함께 만들어보고 싶습니다.
정규 근로 시간을 지키는. 야근 없는 회사와 거래합니다.

각 분야별. 좋은 책'이나 사이트' 블로그' 링크 소개 받습니다. shintx@naver.com

댓글 달기

Filtered HTML

  • 텍스트에 BBCode 태그를 사용할 수 있습니다. URL은 자동으로 링크 됩니다.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>
  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.

BBCode

  • 텍스트에 BBCode 태그를 사용할 수 있습니다. URL은 자동으로 링크 됩니다.
  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param>
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.

Textile

  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • You can use Textile markup to format text.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>

Markdown

  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • Quick Tips:
    • Two or more spaces at a line's end = Line break
    • Double returns = Paragraph
    • *Single asterisks* or _single underscores_ = Emphasis
    • **Double** or __double__ = Strong
    • This is [a link](http://the.link.example.com "The optional title text")
    For complete details on the Markdown syntax, see the Markdown documentation and Markdown Extra documentation for tables, footnotes, and more.
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>

Plain text

  • HTML 태그를 사용할 수 없습니다.
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.
  • 줄과 단락은 자동으로 분리됩니다.
댓글 첨부 파일
이 댓글에 이미지나 파일을 업로드 합니다.
파일 크기는 8 MB보다 작아야 합니다.
허용할 파일 형식: txt pdf doc xls gif jpg jpeg mp3 png rar zip.
CAPTCHA
이것은 자동으로 스팸을 올리는 것을 막기 위해서 제공됩니다.