생성자/소멸자가 호출되지 않습니다.
글쓴이: hyunya77 / 작성시간: 토, 2012/10/27 - 2:19오전
#include <stdio.h> class Transport { public: virtual void transportFunc() = 0; }; class MyTransport : public Transport { public: MyTransport(); virtual ~MyTransport(); virtual void transportFunc(); }; MyTransport::MyTransport() { printf("%s\n", __func__); } MyTransport::~MyTransport() { printf("%s\n", __func__); } void MyTransport::transportFunc() { printf("MyTransport::%s\n", __func__); } class Test { public: Test(); virtual ~Test(); Transport *m_trans; void testFunc(); }; Test::Test() { printf("%s\n", __func__); } Test::~Test() { printf("%s\n", __func__); } void Test::testFunc() { printf("%s\n", __func__); m_trans = new MyTransport(); m_trans->transportFunc(); delete m_trans; } int main() { Test test; test.testFunc(); return 0; }
위와 같은 코드입니다만,
MyTransport() 와 ~MyTransport()가 호출되지 않고있습니다.
m_trans 변수가 Transport 부모 class type이니 (정의되어 있지는 않지만) Transport(), ~Transport()가 대신
호출되고 있는 것이라 짐작하고 있습니다.
하지만 여기까지는 짐작이 가는데, "delete m_trans"시에 MyTransport() 와 ~MyTransport()가 호출되었으면 합니다.
그런데 어떻게 수정하면 될지 잘 모르겠네요. 상속구조자체는 그대로 두고 상속받은 클래서의 생성/소멸자가
호출되게 하려면 어떻게 해야하나요?
Forums:
참고로 위 소스의 실행결과는 아래와 같습니다.
이렇게 고치니 아래처럼 동작하네요.
아직 왜 해결이되었는지는 모르겠습니다. -_-; 잘 아시는분 설명 좀 부탁드립니다.
간단한 이유가 있습니다.
제가 정말 좋아하는 책, Effective C++(스콧 마이어스 지음, 곽용재 옮김) 항목 7에 이런 내용이 있습니다.
"다형성을 가진 기본 클래스에서는 소멸자를 반드시 가상 소멸자로 선언하자."
다름이 아니라 hyunya77님께서 겪으시는 문제는 기본 클래스인 Transport가 가상 소멸자를 가지지 않아서 생긴 문제입니다.
가상 함수를 사용하셨으니 그게 무엇이며, 어떻게 동작하는지는 이해하셨으리라 생각합니다.
문제는 여기에 있습니다.
void Test::testFunc()
{
printf("%s\n", __func__);
m_trans = new MyTransport();
m_trans->transportFunc();
delete m_trans;
}
delete m_trans;를 수행할 때, 컴파일러는 적합한 소멸자를 찾아 호출해 줘야 합니다.
그런데 소멸자가 가상 함수가 아니라면 이 과정은 정적 바인드가 수행되고, 따라서 m_trans의 타입에 의존합니다,
근데 m_trans는 Transport * 타입이죠. 그래서 컴파일러는 이 포인터가 Transport를 가리키고 있다고 생각하고 Transport를 소멸시키기 위한 코드를 작성합니다.
바로 위에서 MyTransport를 생성해서 집어넣었는데도 말이죠. 컴파일러는 그런 걸 신경쓰지 않아요.
결국 Transport의 소멸자가 호출되기 때문에 MyTransport의 소멸자는 무시당하게 됩니다.
소멸자가 가상 함수로 선언되어야만 m_trans의 타입과 관계 없이 런타임에서 m_trans가 가리키는 객체의 정확한 타입을 알아내고, 그에 적합한 소멸자를 호출할 수 있게 되는 겁니다.
C++에서 상속받지 않은 클래스의 기본 소멸자는
C++에서 상속받지 않은 클래스의 기본 소멸자는 무조건 비가상함수입니다.
상속받은 클래스의 경우는 부모 클래스의 소멸자가 가상함수면 가상함수가 되고 비가상함수면 자식클래스의 소멸자도 비가상함수가 됩니다.
처음 올린 예제는 기본 클래스의 소멸자가 선언되어있지 않으므로 기본소멸자가 쓰이고 따라서 이는 비가상함수이기때문에 자식 클래스의 소멸자가 호출되지 않은 겁니다.
두번째 예제는 명시적으로 가상 함수로 소멸자를 선언했기 때문에 해결된 것입니다.
감사합니다.
소멸자를 왜 보통 가상함수로 선언하는지도 의문이었는데, 이제 그 이유를 알것갔습니다.
시간내서 답글달아주셔서 감사합니다. ^^
댓글 달기