以下は、コードの 2 つの断片 (コンパイル可能) です。最初のフラグメントでは、構造体の前方宣言のみを使用しているときに、この構造体へのポインターを基本クラスから削除していますが、Guest クラスの dtor は呼び出されません。
2 番目のフラグメントでは、前方宣言の代わりに、Base での削除を使用してこの Guest クラスの完全な定義を使用し、意図したとおりに動作します。
なんで?なぜ違いが生じるのですか?前方宣言は、このクラス/構造体の定義が別の場所にあるというコンパイラーへの単なるメモではないでしょうか?
それが直感的に機能しないことに非常に驚いています。
//First just forward dclr
#include "stdafx.h"
#include <iostream>
using std::cout;
struct Guest;
struct Base
{
Guest* ptr_;
Base(Guest* ptr):ptr_(ptr)
{
cout << "Base\n";
}
~Base()
{
cout << "~Base\n";
delete ptr_;
}
};
struct Guest
{
Guest()
{
cout << "Guest\n";
throw std::exception();
}
Guest(int)
{
cout << "Guest(int)\n";
}
~Guest()
{
cout << "~Guest\n";
}
};
struct MyClass : Base
{
Guest g;
MyClass(Guest* g):Base(g)
{
cout << "MyClass\n";
}
~MyClass()
{
cout << "~MyClass\n";
}
};
int _tmain(int argc, _TCHAR* argv[])
{
try
{
Guest* g = new Guest(1);
MyClass mc(g);
}
catch(const std::exception& e)
{
std::cerr << e.what();
}
return 0;
}
// 2 番目 - 完全な定義
#include "stdafx.h"
#include <iostream>
using std::cout;
struct Guest
{
Guest()
{
cout << "Guest\n";
throw std::exception();
}
Guest(int)
{
cout << "Guest(int)\n";
}
~Guest()
{
cout << "~Guest\n";
}
};
struct Base
{
Guest* ptr_;
Base(Guest* ptr):ptr_(ptr)
{
cout << "Base\n";
}
~Base()
{
cout << "~Base\n";
delete ptr_;
}
};
struct MyClass : Base
{
Guest g;
MyClass(Guest* g):Base(g)
{
cout << "MyClass\n";
}
~MyClass()
{
cout << "~MyClass\n";
}
};
int _tmain(int argc, _TCHAR* argv[])
{
try
{
Guest* g = new Guest(1);
MyClass mc(g);
}
catch(const std::exception& e)
{
std::cerr << e.what();
}
return 0;
}