안된다는걸 오늘 처음 알았습니다. ㅠ ㅠ
C++ Builder에서는 TObject를 상속받았을 경우 소멸자에서 가상함수를 호출해도 상관 없습니다.
다행스럽게도 그동안 RTTI정보를 이용하느라 대부분의 클래스를 TObject를 상속받아서 만들었기 때문에 기존 소스를 수정하는 난리는 치지 않아도 되겠지만... 이런걸 이제서야 알다니...
아주 간단한 예제입니다.
class TParent
{
public:
TParent() {}
virtual ~TParent() {
printf("~TParent called\r\n");
Close();
}
virtual void __fastcall Close() {
printf("TParent::Close() called\r\n");
}
};
class TChild : public TParent
{
public:
TChild() : TParent() {}
virtual ~TChild() {
printf("~TChild called\r\n");
}
virtual void __fastcall Close() {
printf("TChild::Close() called\r\n");
}
};
main()
{
TParent *a = (TParent*)new TChild();
delete a;
}
결과는 직접 해 보시면 아시겠지만 TChild객체인 a가 파괴될 때 TChild::Close()가 아닌 TParent::Close()가 호출이 됩니다. Close()를 순수 가상함수로 선언했을 경우엔 걍 뻗습니다. 쭈욱~~~
VC++에서도 마찬가지입니다(6.0, 2003).
대충 파악하기론... TParent의 소멸자보다 TChild의 소멸자가 먼저 실행되면서 vtable이 변경되는게 문제인 듯 합니다.
만약 TParent를 TObject를 상속받게 만들면 TChild::Close()가 제대로 호출됩니다. TObject관련 도움말에도 약간의 힌트가 될만한 글이 적혀 있더군요.
혹시나 VC++에서도 CObject를 상속받으면 되나 싶어서 해 봤는데 역시 안되더군요.
그나저나 소멸자에서 가상함수를 안쓰는 방향으로 하려고하니... 제가 지금 만들고 있는 프로그램에선 무지 불편하네요. 에효...
모르고 계셨던 분이 혹시 계실까 싶어서 끄적여봅니다.
|
( __fastcall 은 삭제했습니다만 )