12

このコードがあるとします

class Base{
  public:
        int getVal();
  private:
         int a, b;
};

class Derived::public Base{
    public:
         void printVal();
};

int main(){
    Base *b = new Derived();
    delete b;    
}

仮想デストラクタが物事を適切に削除することは知っていますが、派生クラスに仮想関数とデータメンバーがなくても、(仮想デストラクタがない場合) ベースポインタで削除するのは悪いことですか? これが行われるとどうなりますか?

4

3 に答える 3

9

派生クラスに仮想関数やデータメンバがなくても(仮想デストラクタがない場合)ベースポインタで削除するのはまずいですか?

はい。

派生クラスの内容に関係なく、動作は未定義です。

これが行われるとどうなりますか?

なんでも起こる可能性がある。

于 2010-10-15T18:01:54.823 に答える
7

プリミティブ型のデータの場合、あなたの例は実際に機能する可能性が最も高いです。実際のところ、vtable を発生させると実際にはパフォーマンスが低下する可能性があります (したがって、ここでの正当な使用がある可能性があります) が、5.3-5.4に従って技術的に定義されていません。

[削除演算子の] オペランドの静的型がその動的型と異なる場合、静的型はオペランドの動的型の基本クラスであり、静的型は仮想デストラクタを持たなければならず、そうでなければ動作は未定義です。

それは実際にはすべてクラス内のデータの「ヒープネス」に依存し、ヒープ割り当てメンバーがないため (あなたの場合)、問題ないはずですが、それは間違いなくコードのにおいです。

于 2010-10-15T18:08:09.773 に答える
2

派生クラスの仮想デストラクターは、派生オブジェクトが基底クラスへのポインターを介して作成されるときに、派生デストラクタを適切に呼び出す (ポリモーフィズム) ために必要です。

高整合性 CPP ルール 3.3.2基本クラスの「仮想」デストラクタを記述します。(QACPP 2116)

正当化: オブジェクトがその基本クラスへのポインターを介して破棄される場合、その基本クラスには仮想デストラクタが必要です。基本クラスのデストラクタが仮想でない場合、基本クラスのデストラクタのみが呼び出されます。ほとんどの場合、デストラクタは仮想である必要があります。これは、保守または再利用によって、仮想デストラクタを必要とする派生クラスが追加される可能性があるためです。

class Base {}; 
class Derived : public Base { public: ~Derived() {} }; 

void foo() {  
   Derived* d = new Derived; delete d; // correctly calls derived destructor 
} 
void boo() { 
   Derived* d = new Derived; Base* b = d; delete b; // problem! does not call derived destructor! 
}
于 2010-10-15T19:15:24.643 に答える