私はこれがなぜ起こっているのか理解していますが、解決しようとして立ち往生しています...私のプログラムが終了したときにエラーが生成されたとき(つまり、クラッシュに至ったとき)に私のコードは何をしています...
pure virtual method called
SomeClass::~SomeClass()
{
BaseClassObject->SomePureVirtualMethod(this);
}
void DerivedClass::SomePureVirtualMethod(SomeClass* obj)
{
//Do stuff to remove obj from a collection
}
new SomeClass
を呼び出すことはありませんが、QList<SomeClass*>
オブジェクトを追加するSomeClass*
を持っています。 SomeClass
のこのデストラクタの目的は、DerivedClass
にSomeClass
の特定のインスタンスをQList<SomeClass*>
のコレクションから削除するように指示することです。
したがって、具体的な例では...
BaseClass
= Shape
DerivedClass
= Triangle
SomeClass
= ShapeProperties
はShape
への参照を所有しています
そのため、new ShapeProperties
を呼び出すことはありませんが、Triangle
内にQList<ShapeProperties*>
があります。 ShapeProperties
のデストラクタは、Triangle
にShapeProperties
の特定のプロパティをQList<ShapeProperties*>
のコレクションから削除するように指示することです。
デストラクタが呼び出されるまでに、継承されたクラスのデストラクタはすでに呼び出されています。コンストラクタとデストラクタ内では、オブジェクトの動的型は静的型と同じであると効果的に見なすことができます。つまり、コンストラクター/デストラクター内から仮想メソッドを呼び出す場合、呼び出されるのはオーバーライドされたバージョンではありません。
SomePureVirtualMethod
をデストラクタで呼び出す必要がある場合は、必要なメソッドの実際の定義があるクラスのデストラクタ内で呼び出す必要があります。
Baseクラスvirtual
のデストラクタでSomeClass
メソッドを呼び出すと、BaseクラスSomeClass
のmethod(SomePureVirtualMethod()
)が呼び出されます。定義のない純粋な仮想メソッド。そしてそれゆえエラー。
なぜこれが起こるのですか?
コンストラクタまたはデストラクタのthis
のタイプは、コンストラクタまたはデストラクタが呼び出されているタイプであるため、動的ディスパッチは、すべてで機能すると予想されるコンストラクタおよびデストラクタでは機能しませんその他の機能。
なぜクラッシュするのですか?
コンストラクタまたはデストラクタから純粋な仮想関数を呼び出すのは未定義の動作であるためです。
C++ 03 10.4/6状態
「メンバー関数は、抽象クラスのコンストラクタ(またはデストラクタ)から呼び出すことができます。そのようなコンストラクタから作成(または破棄)されるオブジェクトに対して直接または間接に純粋仮想関数を仮想呼び出し(10.3)する効果(またはデストラクタ)は未定義です。」
それを回避する方法?
コンストラクタまたはデストラクタから純粋な仮想関数を呼び出さないことを確認してください。
関連するダイナミクスを理解している場合を除き、コンストラクタまたはデストラクタでvirtual
メソッドを呼び出さないでください。