2012-03-04 3 views
-2

C++ 상속에 관한 몇 가지 질문 :C++ baseconstructor는 언제 실행됩니까?

baseconstructors의 코드는 어떤 순서로 실행됩니까?

이 주문에 영향을 줄 수있는 방법이 있습니까? (예를 들어, 다른 언어에서는 생성자 내의 "super()"를 어딘가에 배치 할 수 있습니다)

생성자에서 기본 클래스의 보호 된 멤버에 액세스해도 괜찮습니까?

+1

각 생성자에'std :: cout'을 추가하여 알아 낸다. –

+0

이게 당신의 숙제입니까? 책을 읽으려고 했습니까? – littleadv

+0

nope -이 코드에 따라 달라지는 코드를 포트에 넣으려고 시도합니다. – Mat

답변

1

클래스 A가 i 기본 클래스 B_i를 가지고 있다고 가정하면 모든 B_i 생성자는 A의 생성자에 대한 코드가 실행되기 전에 실행됩니다. 유일한 예외는 기본값이 아닌 생성자를 사용하여 기본 클래스를 초기화 할 때 실행되지만 일단 모든 기본 클래스가 실행되고 초기화 프로그램 목록에서 처음으로 이동해야합니다. 기본 클래스가 이미 생성되었으므로 기본 클래스의 보호 된 멤버에 액세스하는 것이 좋습니다. 예를 들어

:

class A : public B, C { 
    A() 
    : B(1), //B and C are now constructed 
    memberOfA(memberOfB) 
    { 
    } 
}; 

B에서 무언가를 필요로 memberOfA 귀하의 회원이 memberOfB라고하면 B가 이미 구성되어 있기 때문에 그 괜찮아요.

+0

기본 코드가 기본이 아닌 생성자로 초기화되는 경우이 기본이 아닌 생성자 코드는 A의 (기본값이 아닌) 생성자 코드 뒤에 실행됩니까? – Mat

+0

"예외"에 대한 문장이 나에게 혼란 스럽습니다. 또한 이니셜 라이저 목록에있는 상위 클래스 생성자의 순서는 생성 순서와 관련이 없습니다. 그들은 클래스 선언문에서 파생 된 순서대로 생성됩니다. –

+1

@Mat 부모 클래스는 클래스에서 선언 된 순서대로 초기화 된 다음 클래스에서 선언 된 순서대로 멤버가 초기화됩니다. 그런 다음 클래스의 생성자 본문이 실행됩니다. 이니셜 라이저는 _how_가 아닌 _how_에 초기화를 지시합니다 (순서에는 영향을주지 않습니다). –

0

"상위"/ 수퍼 클래스의 생성자는 항상 첫 번째로 호출됩니다. 이것은 다중 상속의 경우 재귀 적으로 true입니다. (그리고 그것은 C++에서 가상 생성자를 실제로 원하지 않는 이유 중 하나입니다.) 수퍼 클래스의 멤버에 액세스하는 경우 : 완벽하게 괜찮습니다. 초기화됩니다.

+0

답변은 대부분 옳다.하지만 다중 상속은 "상위 클래스"가 문제의 클래스가 여러 클래스에서 상속되는 것이 아니라 세 번째 클래스에서 파생 된 것임을 의미합니다. –

1

구성 순서는 C++에서 잘 정의되어 있습니다. 구성은 (대부분의 파생 형식)의 초기화 목록에서 시작되며 다른 모든 생성자가 호출됩니다. 먼저 가상 기지, 다른 선언의 직계 기지 (이것들은 trun에서 자신의 기지와 구성원을 구성하기 위해 동일한 순서를 적용합니다) 그리고 마지막으로 구성원을 클래스의 선언 순서대로 정렬하지 않습니다. 생성자는 초기화리스트에서 호출 된 것처럼 보입니다.

구조가 생성되는 순서에 영향을 줄 수있는 방법이 없으며 파생 된 형식의 구성 내에서 기본 멤버에 액세스하는 것이 안전합니다. 아마도 놀라운 사실은 반대 방향에서 기본 생성자에서 가상 함수를 호출한다는 것입니다. 건설 공정의 각 단계에서 물체의 유형이 변경됩니다. 즉, 모든 B_i 하위 객체가 완료되고 X의 첫 번째 멤버가 시작하기 전에 B_i가있는 유형 X의 객체가 주어지면 객체 유형이 X가됩니다.이 의미는 기본에서 가상 메소드를 호출하는 것입니다 클래스가 파생 될 최종 유형이 아닌 해당 기본 클래스로 전달됩니다.

+0

"모든 B_i 하위 오브젝트 다음에 만 오브젝트의 유형이 X가됩니다. 오브젝트의 생성자가 * completed * 일 때 오브젝트의 타입은'X'입니다. 그 기반과 멤버를 구축하는 것뿐만 아니라 생성자 함수 자체의 본문을 실행했습니다. 그때까지 아직 X가 아닙니다. –

+0

@ NicolBolas : 나는 그렇게 생각하지 않는다. 표준에서는 데이터 멤버의 생성자 및 * mem-initializer *에서 가상 멤버 함수를 호출 할 수 있으며 호출되는 생성자 클래스에 호출이 전달된다는 것을 분명하게 명시합니다. 또한이 시점에서 * typeid *는 현재 구성중인 클래스의 유형을 참조하는 * type_info * 객체를 반환합니다. 그 점은 특정 점에서 객체의 유형이 생성되는 유형 (12.7/4,5)과 같아 보입니다. –

+0

글쎄, 이것 [오브젝트 구성 및 오브젝트 수명에 대한 정보] (http://www.gotw.ca/publications/mill13.htm)를 고려하십시오. 그것은 동의하지 않는 것 같습니다. –

관련 문제