オブジェクトの基本クラスのデストラクタのみを呼び出すことによって引き起こされた、コード内のメモリ リークを発見しました。この問題は理解されています。virtual
インターフェイス クラスのデストラクタにを既に追加しましたMyÌnterface
。私を困惑させているのは、MyHelper
最終的に呼び出される私のヘルパー クラスの標準デストラクタが明らかにコンパイラによって作成されたことです。これを 2 つの異なるコンパイラで試しました。
メンバーまたは基本クラスが制限を導入すると、ほとんどのデフォルト実装が作成されないことに気付いたので、これは私にとって非常に驚きでした。デストラクタの保護が継承されないのはなぜですか?
#include <iostream>
class MyInterface
{
public:
virtual void doSomethingUseful()=0;
// a lot more functions declared omitted
virtual void doSomethingElse()=0;
virtual void doSomethingIndividual()=0;
protected:
/// protected destructor to forbid calling it on interfaces
~MyInterface() {} // HERE the virtual is clearly missing
};
/// a common base that defaults most functions implementations
class MyHelper: public MyInterface
{
public:
void doSomethingUseful() {}
// a lot more default implementations omitted
void doSomethingElse() {}
};
class SomeImplementation: public MyHelper
{
public:
SomeImplementation()
{
std::cout << "SomeImplementation ctr" << std::endl;
}
~SomeImplementation()
{
std::cout << "SomeImplementation dtr" << std::endl;
}
void doSomethingIndividual()
{
std::cout << "SomeImplementation did it." << std::endl;
}
};
/// user of MyInterface cannot delete object mi passed as parameter
int deleteSafeUsage(MyInterface& mi)
{
mi.doSomethingIndividual();
// would cause a compiler error: delete &mi;
}
/// usage restricted to MyHelper level, only exception is object creation
int testIt()
{
MyHelper* h = new SomeImplementation;
deleteSafeUsage(*h);
delete h; // <- HERE the memory leak happens!
}
上記のコード例の出力は、欠落している を「示しています」SomeImplementation ctr
:
SomeImplementation ctr
SomeImplementation did it.