프로그래밍 일반/C++ 프로그래밍

[C++] 생성자/파괴자에서 virtual 함수를 호출

지노윈 2022. 1. 18. 15:05
반응형

생성자/파괴자에서 virtual 함수를 호출하는 것에 대해서는 입사를 위한 시험에서 많이 출제되거나 질문이 되어지는 내용입니다.

 

다음 코드의 출력 결과는 어떻게 될지 고민해 보시기 바랍니다.

#include <iostream>

using namespace std;

class Base
{
public:
    Base() {
        cout << "Base" << endl;
        Do();
    }
    virtual ~Base() {
        cout << "~Base" << endl;
    }
    virtual void Do() {
	    cout << "Base::Do" << endl;
    }
};

class Derived : public Base
{
public:
    Derived() {
        cout << "Derived" << endl;
    }
    ~Derived() {
        cout << "~Derived" << endl;

    }
    virtual void Do() {
	    cout << "Derived::Do" << endl;
    }
};

int main()
{
    Derived* base = new Derived;
    delete base;
}

결과는 아래 "더보기"를 눌러서 확인해 주세요.

더보기

Base

Base::Do

Derived

~Derived

~Base

Do는 virtual 함수로 구현 되었고 Derived 객체를 생성하여 호출을 하는 것이므로 Derived::Do가 호출되어야 하지만 결과는 Base::Do가 호출 됩니다. 즉, virtual 함수이지만 일반 함수와 같이 동작합니다.

~Base에서 Do를 호출해도 동일한 결과를 얻습니다. 

이와 같이 일반 함수로 동작하는 이유는 Base 클래스가 생성자 또는 파괴자가 실행되는 시점에는 Derived 클래스는 존제하지 않기 때문에 당연한 결과입니다.

 

만약, Do가 순수 가상 함수라면 어떻게 될까요?

 

Base 클래스의 Do 함수를 다음과 같이 선언합니다.

class Base
{
public:
	...
    
    //virtual void Do() {
	   // cout << "Base::Do" << endl;
    //}

    virtual void Do() = 0;
};

이 경우는 컴파일 타임에 다음과 같은 링크 오류가 발생합니다.

error LNK2019: unresolved external symbol "public: virtual void __thiscall Base::Do(void)" (?Do@Base@@UAEXXZ) referenced in function "public: __thiscall Base::Base(void)" (??0Base@@QAE@XZ)

 

생성자/파괴자에서는 virtual 함수를 호출하면 의도하지 않은 동작을 할 수 있으니 주의해주세요!!!