2016-04-25 3 views
2

私はこのような状況を持っている:メンバデストラクタの実行時にクラスにはどのような型の仮想関数がありますか?

#include <iostream> 

struct B { virtual void f() { std::cout << "base"; } }; 

struct A { 
    ~A() { 
     b->f(); 
    } 

    B *b; 
}; 


struct Bd : B { 
    Bd():a{this}{ } 
    ~Bd() { } 
    virtual void f() { std::cout << "derived"; } 

    A a; 
}; 

int main() { 
    Bd d; 
} 

は、このプリントは「由来する」ことを保証しますか?

+1

私は 'B :: f'を呼び出すか、未定義の動作を呼び出すと考えています。オブジェクトのライフタイムは、(デストラクタが始まると)正式に終了するので、 'A ::〜A 'が' b-> f()を呼び出すと、 ; '、' b'の派生部分は既に死んでいます。 – Quentin

+0

また、[this](http://stackoverflow.com/questions/12092933/calling-virtual-function-from-destructor) – sp2danny

+0

@Quentin見てまったく見えません。あなたは間違いなく、それ自身のデストラクタからオブジェクトにアクセスすることができます。これは、その存続期間が終わるとアクセスを禁止することと反対です。 –

答えて

2

[class.cdtor]/4

仮想関数([class.virtual])を含む

メンバー関数は、 構築または破壊([class.base.init])中に呼び出すことができます。 仮想関数は、がクラスの非静的データメンバの建設や破壊 中を含め、コンストラクタ またはデストラクタから直接または間接的に呼び出さと コールが適用されるオブジェクトは、(オブジェクトである場合それをと呼びます)、または 破壊の場合は、 コンストラクタまたはデストラクタのクラスの最後のオーバーライドで、 より派生したクラスでオーバーライドしません。それはBdf()の最終overriderを呼び出し、derivedを印刷する必要がありますので、ここで問題になって

「クラス」は、Bdです。

0

私は今それを調べる時間がありませんが、デストラクタを実行しているオブジェクトの仮想呼び出しは、デストラクタが現在実行中のクラスに移動するというルールがあります。そのため、Bdのデストラクタでは、aのデストラクタが実行され、b->f()のコールはBd::fとなります。

aB代わりのBdのメンバーであった場合aのデストラクタがBのデストラクタから実行してしまうため、コールは、B::fに行くだろう。

メカニズムを考えるのが好きなら(私は一般的にそうではありません)、vtableの観点から考えてください。デストラクタに入ると、コードはvtableポインタが実行中のデストラクタに属するvtableを指すように設定します。