27

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

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*SomeClassDerivedClassSomeClassQList<SomeClass*>

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

BaseClass=Shape

DerivedClass=Triangle

SomeClass=ShapePropertiesへの参照を所有しているShape

だから、私は電話をかけることはありませんがnew ShapeProperties、のQList<ShapeProperties*>中にはありTriangleます。のデストラクタは、のコレクションからの特定のプロパティを削除するShapePropertiesように指示します。TriangleShapePropertiesQList<ShapeProperties*>

4

3 に答える 3

39

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

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

于 2012-05-22T17:51:31.180 に答える
14

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

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

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

C ++ 03 10.4/6状態

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

それを回避する方法は?
コンストラクタまたはデストラクタから純粋仮想関数を呼び出さないように注意してください。関連するダイナミクスを理解していない限り、コンストラクタまたはデストラクタでメソッドを
呼び出さないでください。virtual

于 2012-05-22T17:54:09.420 に答える
1

コンパイラとシステムによっては、これが発生する可能性がある別の理由があります。これは、ぶら下がっている参照によるものです。Paul SR Chisholmは、解放されたメモリの可能な状態について説明しています。

  • メモリは割り当て解除としてマークされる場合があります。
  • メモリが意図的にスクランブルされている可能性があります。
  • メモリが再利用される可能性があります。
  • 記憶はそのまま残っていたのかもしれません。

最後は興味深いケースです。「まさにその通り」のオブジェクトは何でしたか?この場合、それは抽象基本クラスのインスタンスでした。確かにそれはvtblが残された方法です。そのようなオブジェクトに対して純粋仮想メンバー関数を呼び出そうとするとどうなりますか?

「と呼ばれる純粋仮想関数」。

于 2020-07-31T23:04:57.370 に答える