2013-04-22 3 views
1

파생 클래스의 객체를 만들 때 왜 생성자가 위에서 아래로 호출되는지 (처음에는 기본 생성자, 파생 생성자) 호출되며 bottom-to-top (첫 번째 파생 생성자, 기본 생성자)생성자 및 소멸자 호출

+0

'Derived' 클래스가 상속 된 클래스'Base'와'Base' 클래스가'BaseProperty'라는 속성을 가졌다면 어떻게 될까요?'Derived'가 그 속성을 생성자에서 설정하려고 했습니까? –

답변

5

새내기를 설명하려면 새 건물을 건설 중이라고 생각하십시오.

당신은 지하 1 층 2 층을 건설합니다. 파괴하는 동안 2 층, 1 층 및 지하를 파괴합니다.

같은 방법으로 개체의 생성/제거가 C++에서 발생합니다.

희망이 이해하는 데 도움이됩니다.

+0

감사를 따라 왜 타당한 이유를 원하는 파생 소멸자 자료 소멸자. 어떤 종류의 데이터 구조 (Stack)가 객체가 생성 될 때 따라 다니는 것처럼 어떤 특별한 이유가 있습니까? – VKR

+0

이렇게 생각하십시오 : 상속이란 무엇을 의미합니까? 당신은 이전의 것을 사용하고 있습니다. 지하 1 층을 건설 했나요? 그것은별로 의미가 없습니다. – Whoami

+0

나는 당신에게 동의하지만 완전히 만족하지는 않는다. 왜냐하면 나는 단지 메모리 할당 또는 그와 같은 어떤 기술적 이유를 의미하는 용어로 대답하기를 원하기 때문이다. – VKR

1

메모리 할당은 호출 생성자와 소멸자와 독립적입니다. 파생 된 객체를 만들 때 전체 유형의 메모리가 할당됩니다.

그런 다음 해당 생성자가 호출됩니다 (기본 생성자 아님). 그러나이 생성자는 먼저 기본 클래스 생성자를 호출합니다. 기본적으로 기본 기본 생성자가 호출되지만 파생 생성자 내에서 기본 생성자를 호출하는 방법을 지정할 수 있습니다. 그러한 클래스가없고 기본 클래스를 생성하는 방법을 지정하지 않으면 컴파일 오류입니다. 여기

class Base { 
    int x; 
public: 
    Base() : x(42) {} 
}; 

class Derived : public Base { 
    int y; 
public: 
    Derived() : Base(), y(1337) {} 
    // is the same as: Derived() {} 
}; 

, Base()은 (는 기본 생성자를 제공하지 않습니다) 수 없습니다 : 당신이 볼 수있는

class Base { 
    int x; 
public: 
    Base(int x) : x(x) {} 
}; 

class Derived : public Base { 
    int y; 
public: 
    Derived() : Base(), y(1337) {} // <-- error! 
    Derived() : Base(42), y(1337) {} // <-- ok! 
}; 

그래서, 기술적으로 파생 된 생성자가 호출되는 첫 번째입니다. 그러나 처음부터 기본 생성자를 호출하기 때문에 실제로는 다른 방법입니다. 기본이 생성 된 다음 파생 클래스가 자체 항목을 "추가"합니다.

파괴는 단순히 반대 방향입니다. 파생 클래스의 인스턴스는 기본 클래스가 파괴되기 전에 기본 클래스에 추가하는 내용을 정리해야합니다.

단순히 건물을 짓는 것으로 생각하십시오. 먼저 기본 건물을 만든 다음 이야기를 추가하고 마지막으로 지붕을 추가해야합니다. 파괴 할 때 먼저 지붕을 제거한 다음 이야기를 꺼내 마침내 기지를 제거하십시오.

+0

자료 생성자 파생 생성자 난 그냥이 계층 구조는이 계층 구조, 예를 들어 그런데 왜 – VKR

0

다른 규칙의 결과입니다 : 모든 기본 생성자는 파생 생성자의 본문을 입력하기 전에 호출되며 모든 기본 소멸자는 파생 된 소멸자의 본문을 남긴 후에 호출됩니다. 우리는 (모든 자료의 기지 생성자는 모든베이스 부재 생성자가 너무 완료 완료 자료가 완벽하게 건설되고에 의존하기 때문에 우리는 그런 일을 쓸 수 있습니다

class BaseMember 
{ 
public: 
    bool Pred(); 
}; 

class DerivedMember 
{ 
public: 
    void DoFirst(bool); 
    void DoLast(bool); 
}; 

class Base 
{ 
public: 
    Base() {baseMember=new BaseMember;} 
    ~Base(){delete baseMember;} 
protected: 
    BaseMember *baseMember; 
}; 

class Derived: public Base 
{ 
public: 
    Derived() 
    { 
     derivedMember=new DerivedMember; 
     derivedMember->DoFirst(baseMember->Pred()); 
    } 
    ~Derived() 
    { 
     derivedMember->DoLast(baseMember->Pred()); 
     delete derivedMember; 
    } 
protected: 
    DerivedMember *derivedMember; 
}; 

:

이 (간략화 됨) 코드를 살펴 보자 Base의 생성자 본문이 완료되었습니다.) 파생 생성자의 본문에 들어가기 전에. 이 방법으로, 우리는 모든 기지의 구성원이 그들이 건설되었다는 것을 알 수 있습니다. 파생 된 소멸자의 몸에 들어가면 아직 아무 것도 파괴되지 않았다는 것을 알 수 있습니다. 따라서 모든 기지 구성원은 여전히 ​​존재한다는 것을 알고 나중에 파괴 될 수 있습니다.

생성자/소멸자 호출 계층 구조는이 논리의 결과입니다.Derived()의 본문을 입력하기 전에 Base 생성자를 호출하고 Base 자체가 BaseOfBase에서 파생되면 Base 생성자는 Base() 본문을 입력하기 전에 BaseOfBase() 생성자를 호출합니다. ~ Derived() 소멸자의 몸체를 남긴 후에 ~ Base() 소멸자를 호출하면 ~ Base() 소멸자가 끝난 후에 ~ BaseOfBase() 소멸자가 호출됩니다.

C++에서 다중 상속 (및 가상 상속)은 호출 계층을 더 복잡하게 만들지 만 이러한 경우에도 동일한 논리가 적용됩니다.