2017-01-17 1 views
0

나는 항상 기본 클래스 생성자/소멸자/친구가 파생 클래스에 상속되지 않는다고 생각 해왔다. 이 링크는 다음을 확인합니다 : http://www.geeksforgeeks.org/g-fact-4/.파생 클래스에 상속되는 기본 생성자?

파생 클래스 이니셜 라이저 목록의 초기화 목록에 기본 클래스 생성자를 작성할 수 있다는 것도 알고있었습니다.

다음과 같이 말하면서 : 나는 그것에 대해 오늘 나의 능력을 검사하려고 노력했다. 그러나 나는이 프로그램의 결과물을 추측하지 못했다.

#include<iostream> 

class A { 
    int x, y; 
    public: 
    A(int a = 0, int b = 0) : x(a), y(b) { 
     std::cout << "A ctor called" << std::endl; 
    } 
    void print_A() { 
     std::cout << "x = " << x << std::endl; 
     std::cout << "y = " << y << std::endl; 
    } 
}; 

class B : public A { 
    int z; 
    public: 
    // I knew that A member can be initilized like this. 
    B(int a = 0, int b = 0, int c = 0) : z(a), A(b, c) { 
     std::cout << "C ctor called" << std::endl; 
     // I was not aware about that. 
     A(b, c); 
    } 
    void print_B() { 
     std::cout << "z = " << z << std::endl; 
    } 
}; 

int main() { 
    B b(1, 2, 3); 
    b.print_A(); 
    b.print_B(); 
} 

출력 : 질문의

A ctor called 
C ctor called 
A ctor called 
x = 2 
y = 3 
z = 1 

커플 :

클래스 'B'를 할 수있는 생성자에 액세스 할 수있는 방법 생성자/desctructors/친구가 기지에서 상속하지 않는 경우
  • , 여기서 'A'클래스의.

  • 어떻게 출력 되나요? A의 두 생성자가 어떻게 호출 되었습니까?

답변

3

이해가 잘못되었습니다. 이 :

// I was not aware about that. 
    A(b, c); 

나던 B의 멤버를 초기화, 그것은 (개념적으로 적어도이) 당신이 말한 경우 다소 유사 생성자의 본문에 임시 이름없는 로컬 변수 생성 :

A a(b, c); 

A의 생성자는 public 멤버이므로 아무 것도 호출 할 수 없습니다.

0

A (b, c)가 호출 될 때마다 생성자가 호출됩니다.

당신은 라인

B(int a = 0, int b = 0, int c = 0) : z(a), A(b, c) { 

에를 호출하면

// I was not aware about that. 
     A(b, c); 

코드가 의도

1

만약 생성자/desctructors/친구로 작동하는 B의 생성자 내부를 요구하고있다 클래스에서 'A'클래스의 생성자에 액세스 할 수 있습니까?

"상속되지 않음"은 "파생 클래스에서 액세스 할 수 없음"을 의미하지 않습니다. 파생 클래스는 확실히 기본 생성자를 참조 할 수 있습니다.B의 생성자 두번을 수행

  • 제 1 액세스가 초기화 목록
  • 제 2 액세스는 B 본문에에의 생성자; 그것은 임시 객체 B의 사용자가 *할 수 없습니다 B(int, int)에 액세스 할 수있을 것이라고 의미 생성자를 상속

을 만듭니다.

이것은 생성자 호출과 같습니다. 임시 객체를 만드는 이유는 무엇입니까?

void foo(const A& a); 

하는 일반적인 방법은 다음과 같이 호출하는 것입니다 :

이 방법을 고려

A a(1, 2); 
foo(a); 

하지만 C++은 또한 별도의 줄에 A을 만들지 않고 호출 할 수 있습니다 :

foo(A(1, 2)); 

이 경우 C++ creat 임시 객체를 가져 와서 foo에 대한 참조를 전달합니다. 쓸 때

C++은 생성자를 호출하여 임시 개체를 만듭니다.

'A'의 두 생성자가 어떻게 호출 되었습니까?

생성자가 두 번 호출됩니다. 그래서 당신은 결과를 얻습니다.

* C++ (11)의 using 메커니즘은 특정 규칙을 따라야 제공, 효과 very similar to constructor inheritance 달성 할 수 있습니다.

0

만약 constructor/desctructors/friends가 base로부터 상속받지 않는다면, 클래스 'B'는 어떻게 클래스 'A'의 생성자에 접근 할 수 있습니까?

이 줄의 의미는 무엇입니까?

// I was not aware about that. 
    A(b, c); 

생각하시는 의미에서 "생성자에 액세스"하지 않습니다. 익명 임시 A을 생성자 함수의 본문에 생성 (및 즉시 삭제)합니다.

어떻게 출력 되나요? A의 두 생성자가 어떻게 호출 되었습니까?

A의 인스턴스 두 개 (기본 클래스 하위 개체 B b)와 익명의 임시 개체를 만들었 기 때문에두 번째 A::A의 인스턴스 주소가 첫번째 다르다는 것을

// in A 
A(int a = 0, int b = 0) : x(a), y(b) { 
    std::cout << "A::A @" << static_cast<void*>(this) << std::endl; 
} 
~A() { 
    std::cout << "A::~A @" << static_cast<void*>(this) << std::endl; 
} 

// in B 
B(int a = 0, int b = 0, int c = 0) : z(a), A(b, c) { 
    std::cout << "B::B @" << static_cast<void*>(this) << std::endl; 
    A(b, c); 
} 
~B() { 
    std::cout << "B::~B @" << static_cast<void*>(this) << std::endl; 
} 

내가 얻을 출력 뭔가

같은
A::A @0xffec7054 
B::B @0xffec7054 
A::A @0xffec704c 
A::~A @0xffec704c 
x = 2 
y = 3 
z = 1 
B::~B @0xffec7054 
A::~A @0xffec7054 

참조 :

여기에 다음과 같은 기록으로,이를 확인하는 쉬운 실험입니다 (그래서 그것은 다른 객체입니다), 그리고 그 뒤에는 A::~A이 붙습니다 (익명의 임시 객체가 범위를 벗어나기 때문에).


주 : 원래 제안은 "생성자를 호출"할 수 있다면

  1. , 그것은

    auto subobject = static_cast<A*>(this); 
    new (subobject) A(b, c); 
    

    같이 보일 것입니다 매우 잘못된 것입니다. A 하위 객체 b은 자신의 생성자가 완료되면 B의 생성자가 시작되기 전에 완전히 구성되었습니다. 같은 공간에서 새 객체를 다시 만들 수는 없으며 이전 객체는 어떻게 될까요?

    이것은 약간의 것처럼 보일 수 있지만 동적으로 할당 된 리소스가있는 객체의 경우 심각한 버그가됩니다. 그것은 허용되지 않습니다.

  2. 이니셜 라이저 목록 : z(a), A(b, c)을 작성했지만 파생 클래스 멤버가 초기화되기 전에 기본 클래스 하위 객체가 생성된다는 것을 알고 있어야합니다. 즉, 당신이 쓴 것과 반대되는 두 가지 일이 일어날 것입니다. 그것은 (필연적으로) 오류가 아니지만, 알만한 가치가 있습니다.

+0

하지만 왜 그것은 생성자 호출과 같습니다. 임시 객체를 만드는 이유는 무엇입니까? –

+0

개체 생성 _does_ 생성자를 호출합니다. 그것이 개체가 생성 된 이유입니다. 그리고'A (b, c)'는 새로운 객체에 이름을 부여하지 않았다는 것을 제외하고는'A (b, c) '와 같습니다. 새로 할당 된 메모리에있는 객체도 생성하는'new A (b, c)'표현식을 비교하십시오 (이 경우 결과로 생성되는'A *'포인터는 일반적으로 명명 된 변수에 저장되지만 객체 자체에는 이름). – Useless

관련 문제