3

次のように、3レベルの深さのクラス階層があります。

class A {
public: 
    virtual ~A() {}

}

class B : public A {
public:
    virtual ~B() {}
    void foo(E *e) {
        e->remove(this);
    }
}

class C : public B {
public:
    ~C() {}
}

class E {
public:
    void remove(A *a) {
        delete a;
    }
}

さて、私が疑問に思っているのはfoo()、のオブジェクトを呼び出すとどうなるかということですC。オブジェクト全体を削除するのでしょうか、それともオブジェクトの一部だけを削除して、その部分をメモリに残しておくのBでしょうか。AC

4

3 に答える 3

5

オブジェクト全体を削除するのでしょうか、それともオブジェクトのBとAの部分だけを削除して、Cの部分をメモリに残しておくのでしょうか。

いいえ。仮想Aデストラクタdelete(およびクラスAには仮想デストラクタがあり、そのすべての子孫にも仮想デストラクタがあります)。これは多重継承にも当てはまります。

于 2013-01-06T14:33:46.347 に答える
2

コード内の仮想デストラクタのおかげで、のAインスタンス全体が正しく機能しますC

于 2013-01-06T14:34:45.190 に答える
2

deleteが指しているオブジェクト全体のメモリを常に解放します。ただし、これは呼び出されたデストラクタには適用されません。削除するオブジェクトの静的タイプのデストラクタを呼び出そうとします。多態的なシナリオでは、これは多くの場合、あなたが望むものではありません。このことを考慮:

struct Base { };

struct Derived : Base
{
    int* i;

    Derived() : i(new int) { }

    ~Derived() { delete i; }
}

void bad()
{
    Base* b = new Derived;
    delete b;
}

bad()Derivedデストラクタが呼び出されることはないため、メモリリークが発生します。これは、bの静的タイプがであるためです。Base*したがって、Base::~Baseと呼ばれます。にはデストラクタが定義されていないBaseため、コンパイラによって提供されるデフォルトの実装が実行されますが、この特定の例では何も実行されません。

ただし、これは例には当てはまりません。ルートクラスのデストラクタを仮想化したため、すべての派生クラスのデストラクタはデストラクタ呼び出しの一部として実行されます。

于 2013-01-06T14:41:00.903 に答える