4

私は 3 つの型を使用するこのテスト コードを作成しました:struct One仮想メンバーを持たない通常の型struct Two : One、純粋な仮想関数と仮想デストラクタを持ち、のインターフェイスをstruct Three : Two実装します。Two

#include <iostream>

struct One
{
    ~One() {
        std::cout << "~One()\n";
    }
};

struct Two : One
{
    virtual ~Two() {
        std::cout << "~Two()\n";
    }

    virtual void test() = 0;
};

struct Three : Two
{
    virtual ~Three() {
        std::cout << "~Three()\n";
    }

    virtual void test() {
        std::cout << "Three::test()\n";
    }
};

int main()
{
    Two* two = new Three;
    two->test();

    One* one = two;
    delete one;
}

当然のことながら、出力は次のようになりました。

Three::test()
~One()

すべてのデストラクタを仮想化する以外に、これを修正する方法はありますか? それとも、プログラマーはこのような状況に陥らないように注意する必要がありますか? これをコンパイルするときに警告がないのは奇妙だと思います。

4

4 に答える 4

2

唯一の「修正」は、へのポインターを介してオブジェクトを削除しないことOneです。

これが頻繁に発生するかどうかは、クラスの使用方法によって異なります。たとえば、標準ライブラリにはunary_function仮想デストラクタがないような構造体が含まれていますが、このように悪用されることはほとんどありません。

于 2012-01-07T11:30:46.183 に答える
2

delete oneオブジェクトの動的タイプが静的タイプと一致せず、静的タイプには仮想デストラクタがないため、未定義の動作が呼び出されます。

このような問題を回避する通常の方法は、デストラクタを public で virtual にするか、protected で non-virtual にすることです (この方法で使用されることが予想されるクラスでは)。

于 2012-01-07T11:37:20.613 に答える
1

注意して、One のデストラクタを仮想にする必要があります。一部のコンパイラはこれについて警告します。

于 2012-01-07T11:26:52.427 に答える
1

派生クラスでデストラクタを機能させたい場合は、それらを仮想として定義する必要があります。それが唯一の方法です。

于 2012-01-07T11:32:19.620 に答える