본문 바로가기
프로그래밍 언어/C++

[C++] 상속 관계에서 생성자 호출순서와 명시적 호출이란?

by 까망 하르방 2021. 7. 4.
반응형

앞서 C++에서 상속 형태에 대해서 알고 싶은 경우에는 아래 글 참고

▶ [C++] 상속(inheritance)이란? 

 

[C++] 상속(inheritance)이란?

- 기존 객체 속성을 물려받아 새로운 객체를 만든다. - 동물     ㄴ 개, 고양이, 닭, 말, 토끼 등 - 여행     ㄴ 해외, 국내, 1박 2일, 당일치기 - 물려주는 부모 역할의 객체를 "기반(Base) 클래스"라

zoosso.tistory.com

 

아래 Code를 보면 main문에서 인자가 있는 파생 클래스를 호출했다.

#include <iostream>

class Base
{
public:
    Base()        { std::cout << "1. Base()" << std::endl; }  
    Base(int val) { std::cout << "2. Base(int val)" << std::endl;}
    ~Base()       { std::cout << "3. ~Base()" << std::endl; }
};

class Derived : public Base
{
public:
    Derived()        { std::cout << "4. Derived()" << std::endl; }
    Derived(int val) { std::cout << "5. Derived(int val)" << std::endl; }
    ~Derived()       { std::cout << "6. ~Derived()" << std::endl; }
};


int main()
{
    Derived d(1);
}

Q) 생성자 호출 순서가 어떻게 될까? 

    "2. Base(int val)"가 출력 될까?

A) NO!

5. Derived(int val)는 예상대로 호출되었지만 1. Base()가 호출되었다.

 

이는 컴파일러가 변경해주는 코드가 아래와 같기 때문이다.

class Derived : public Base
{
public:
    Derived()        { } // -> Derived() : Base() {}
    Derived(int val) { } // -> Derived(int a) : Base() {}
    ~Derived()       { } // -> ~Derived() {~ Base();}
};

이로인해 파생클래스에서 인자가 있는 것을 호출해도 

기반 클래스(Base)에서는 기본생성자가 호출된다.

→ 상속할 때 생성자 호출 원리를 아는 것은 중요하다.

    ① 컴파일러는 기반 클래스의 생성자를 호출하는 코드를 자동으로 추가한다.

        main 함수에서 인자가 있던 없던 기반 클래스의 default 생성자가 호출되는 셈.

    ② 파생 클래스 객체 생성시 기반 클래스트의 기본 생성자부터 먼저 수행된다.

 

main 문에서 인자가 있는 것으로 호출 했기 때문에 

 

상속 관계상 아래 순서대로 호출되어야 할 것 같다.

위 코드에서는 실제로 기반 클래스에서 

Default 생성자인 "Base()"를 삭제하면 Error 가 발생한다.

 

How?

- 기반 클래스에 기본 생성자가 있다면 문제 없지만 그렇지 않은 경우 문제가 발생한다.

   이때는 사용자가 기반 클래스 생성자를 명시적으로 호출해야 한다.

#include <iostream>

class Base
{
public:
    Base(int val) { std::cout << "2. Base(int val)" << std::endl; }
    ~Base()       { std::cout << "3. ~Base()" << std::endl; }
};

class Derived : public Base
{
public:
    Derived() : Base(0)          { std::cout << "4. Derived()" << std::endl; }
    Derived(int val) : Base(val) { std::cout << "5. Derived(int val)" <<  std::endl; }
    ~Derived()                   { std::cout << "6. ~Derived()" << std::endl; }
};

int main()
{
    Derived d(1);
}

명시적으로 호출해주었기 때문에 기반 클래스에서 반드시 기본 생성자가 있을 필요가 없다.

반응형

댓글