web-dev-qa-db-ja.com

「呼び出された純粋な仮想メソッド」を解決する方法

私はこれがなぜ起こっているのか理解していますが、解決しようとして立ち往生しています...私のプログラムが終了したときにエラーが生成されたとき(つまり、クラッシュに至ったとき)に私のコードは何をしています...

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のこのデストラクタの目的は、DerivedClassSomeClassの特定のインスタンスをQList<SomeClass*>のコレクションから削除するように指示することです。

したがって、具体的な例では...

BaseClass = Shape

DerivedClass = Triangle

SomeClass = ShapePropertiesShapeへの参照を所有しています

そのため、new ShapePropertiesを呼び出すことはありませんが、Triangle内にQList<ShapeProperties*>があります。 ShapePropertiesのデストラクタは、TriangleShapePropertiesの特定のプロパティをQList<ShapeProperties*>のコレクションから削除するように指示することです。

19
user869525

デストラクタが呼び出されるまでに、継承されたクラスのデストラクタはすでに呼び出されています。コンストラクタとデストラクタ内では、オブジェクトの動的型は静的型と同じであると効果的に見なすことができます。つまり、コンストラクター/デストラクター内から仮想メソッドを呼び出す場合、呼び出されるのはオーバーライドされたバージョンではありません。

SomePureVirtualMethodをデストラクタで呼び出す必要がある場合は、必要なメソッドの実際の定義があるクラスのデストラクタ内で呼び出す必要があります。

30
K-ballo

BaseクラスvirtualのデストラクタでSomeClassメソッドを呼び出すと、BaseクラスSomeClassのmethod(SomePureVirtualMethod())が呼び出されます。定義のない純粋な仮想メソッド。そしてそれゆえエラー。

なぜこれが起こるのですか?
コンストラクタまたはデストラクタのthisのタイプは、コンストラクタまたはデストラクタが呼び出されているタイプであるため、動的ディスパッチは、すべてで機能すると予想されるコンストラクタおよびデストラクタでは機能しませんその他の機能。

なぜクラッシュするのですか?
コンストラクタまたはデストラクタから純粋な仮想関数を呼び出すのは未定義の動作であるためです。

C++ 03 10.4/6状態

「メンバー関数は、抽象クラスのコンストラクタ(またはデストラクタ)から呼び出すことができます。そのようなコンストラクタから作成(または破棄)されるオブジェクトに対して直接または間接に純粋仮想関数を仮想呼び出し(10.3)する効果(またはデストラクタ)は未定義です。」

それを回避する方法?
コンストラクタまたはデストラクタから純粋な仮想関数を呼び出さないことを確認してください。
関連するダイナミクスを理解している場合を除き、コンストラクタまたはデストラクタでvirtualメソッドを呼び出さないでください。

10
Alok Save