1
#include <iostream>

using namespace std;
int *p1;
struct base
{
    base():a(10){}
    int a;
    ~base()
    {
        cout << "~base()\n";
    }
};

struct derive:public base
{
    derive():b(5){

        p1=&b;
        cout << p1 << "\n";

    }
    int b;
    ~derive()
    {
        cout << "~derive()\n";
    }
};
int main()
{
    base *p = new derive;
    delete(p);
    cout << *p1;
    return 0;
}

派生の b は削除しないほうがいいと思いますが、p1 が指しているものは削除されていました。動的継承が発生しなかったときに派生クラスを指していた基本クラスのポインターを削除すると、どのように機能しますか? 私の英語でごめんなさい。

4

3 に答える 3

4

基本クラスのデストラクタがそうではないため、これは未定義の動作virtualです。UBは何でも起こり得ることを意味します。

基本クラスに仮想デストラクタがない場合は、基本クラスを介して派生オブジェクトを削除しないでください。

于 2012-04-19T13:53:42.867 に答える
0

次のコードで期待されること

base *p = new derive;
delete(p);

p が指す派生オブジェクトが正しくクリーンアップされていることです。これは、基本クラスに仮想デストラクタがある場合にのみ実行できます。これはここでは当てはまらないため、派生デストラクタで発生するクリーンアップは発生しません。これは不健康な状況です (または、ルシアンによってより技術的に言えば、未定義の動作)。

于 2012-04-19T13:54:14.257 に答える
-1

私は 100% ではありませんが、質問を理解しています。c++ を使用してからしばらく経ちましたが、試してみます。

通常、動的に割り当てられるオブジェクトがある場合、私の教師が「悪の三部作」と呼んでいた 3 つのものが必要です。

  1. コンストラクターのコピー
  2. 代入演算子
  3. 仮想デストラクタ

最初の 2 つは「ディープ コピー」の作成に関係しており、3 番目は私たちが関心を持っていることです。

オブジェクト仮想テーブルに追加するには、デストラクタを仮想としてマークする必要があります。これにより、デストラクタはチェーンを呼び出します。

それで:

class A
{
    public A(A & copy) { ... }
    public static A & operator = (A & rhs) { ... }
    virtual ~A() { ... }
}

class B : A { } // inherits A's destructor via virtual table
于 2012-04-19T13:56:56.033 に答える