3

C ++ FAQ Liteのセクション16.15で説明delete thisし、次に言及します。

当然、仮想デストラクタがない場合に、このポインタが基本クラスへのポインタである場合は、通常の警告が適用されます。

なぜこれが本当ですか?このコードを考えてみましょう:

class ISuicidal {
public:
    virtual void suicide() = 0;
};

class MyKlass : public ISuicidal {
public:
    MyKlass() {
        cerr << "MyKlass constructor\n";
    }

    ~MyKlass() {
        cerr << "MyKlass destructor\n";
    }

    void suicide() {
        delete this;
    }
};

このように使用されます:

int main()
{
    ISuicidal* p = new MyKlass;
    p->suicide();
    return 0;
}

呼び出しでは、仮想デストラクタがない場合でもp->suicide()、のデストラクタがMyKlass期待どおりに呼び出されます。ISuicidal

私にとって、これは理にかなっています。なぜなら、MyKlass::suicideでは、の静的タイプはでthisあることがわかっているMyKlass*ので、正しいデストラクタが呼び出されるからです。typeidこれは、内に電話をかけることで簡単に確認できsuicideます。

それで、FAQエントリは不正確ですか、それとも私はそれを誤解していますか?

4

6 に答える 6

5

あなたは誤解しています。ISuicidalに自殺関数を実装する(つまり、これを削除する)と、このポインターが基本クラスである場合、deleteを呼び出すと、派生クラスのデストラクタが呼び出されないことがわかります。

于 2011-09-16T06:03:47.747 に答える
4

ここでsuicide(), 使用している関数では、ポインターはクラスMyKlassに対応しています。これは、関数がISuicidalではなくMyKlassで定義されているため、MyKlassのデストラクタが呼び出されるためです。delete this;
this

ISuicidalで関数を定義した場合、ISuicidalで仮想デストラクタを宣言しない限り、MyKlassのデストラクタは呼び出されません。

于 2011-09-16T06:06:52.230 に答える
2

MyClassから派生した別の実クラス(MyClass2など)を階層に導入すると、問題が発生します。

class ISuicidal {
public:
    virtual void suicide() = 0;
};

class MyKlass : public ISuicidal {
public:
    MyKlass() {
       cerr << "MyKlass constructor\n";
    }

    ~MyKlass() {
        cerr << "MyKlass destructor\n";
    }

    void suicide() {
        delete this;
    }
};

class MyKlass2 : public MyKlass {
public:
    MyKlass2() {
        cerr << "MyKlass2 ctr"<<std::endl;
    } 

    ~MyKlass2() {
        cerr << "MyKlass2 dtr"<<std::endl;
    }
}

int main()
{
    MyKlass* p = new MyKlass2;
    delete p; //destructor of base class called, not the destructor of MyKlass2 because
              //the destructor is not virtual
    return 0;
}
于 2011-09-16T06:09:12.550 に答える
2

class Child : public MyKlass { ~Child () {} };

ISuicidal* p = new Child;

p->suicide(); // ~Child() not called !

于 2011-09-16T07:29:28.970 に答える
0

インスタンスの正確なデストラクタを呼び出す限り、安全です(たとえば、ベースのデストラクタを呼び出さないでください)。

したがって、すべてのサブクラスに適切に実装するか、 (またはの存続期間を管理するものに)suicide()アクセスできる外部削除関数を作成することで、これを安全に実行できます。thisthis

于 2011-09-16T06:03:41.943 に答える
0

あなたはそれを誤解していると思います。この問題は、基本クラスでdelete thisを呼び出す場合、つまり、thisポインターが基本クラスへのポインターのタイプを持っている場合に発生します。

当然、仮想デストラクタがない場合に、このポインタが基本クラスへのポインタである場合は、通常の警告が適用されます。

あなたの例では、これは基本クラスへのポインタではなく、派生クラスへのポインタです。

于 2011-09-16T06:05:09.633 に答える