デストラクタから派生クラスの仮想メソッドを呼べない?

[戻る]
夢幻 2004/04/02(金) 18:04:14
あるクラス「A」があって、その派生クラス「B」があるとします。
クラス「B」が破棄されるとき「B::~B()」→「A::~A()」の順番でデストラクタが呼ばれます。
「A::~A」のときにクラス「B」の仮想メソッド(クラス「A」で定義されクラス「B」にオーバー
ライドされている)を呼び出そうとした時、クラス「A」の仮想メソッドが呼ばれてしまいます。
これは「A::~A()」の時にクラス「B」は破棄されてしまっているということなのでしょうか?

開発環境:Win2000、VC++6.0、APIのみ

無責任 2004/04/02(金) 18:22:51
なんかよく分りませんが、クラスAを作って破棄している分にはクラスBは関係ありません。
動的に作成したクラスBのポインタをクラスAのポインタにキャストさせた後、
クラスAのポインタでdeleteしてみたら分ると思います。

YuO [E-Mail] 2004/04/02(金) 18:55:23
> 「A::~A」のときにクラス「B」の仮想メソッド(クラス「A」で定義されクラス「B」
にオーバー
> ライドされている)を呼び出そうとした時、クラス「A」の仮想メソッ
ドが呼ばれてしまいます。
> これは「A::~A()」の時にクラス「B」は破棄されてしまっているということなのでしょ
うか?

そういうことです。
コンストラクタ/デストラクタ中では,仮想関数も静的に解決されます。

関連することでは,επιστημηさんがこんな記事を書いていますね。
http://www.s34.co.jp/cpptechdoc/article/sizeof/

夢幻 2004/04/02(金) 19:22:30
[[解決]]
やはりそういうものなのだったのですね。疑問も解決しました。
有難うございました。

とおり 2004/04/04(日) 22:32:32
>コンストラクタ/デストラクタ中では,仮想関数も静的に解決されます。

静的に解決されるというか、その時点のクラスとして解決されるのでは?
実装依存?

この辺のC++の仕様の詳細を把握してないですが、私が触ったいくつかのコンパイラでは
ctor/dtor中でのvirtual callは、構築途中の段階のクラスとして(= A-B-Cという継承
関係がある場合、Bのctor/dtor内でのvirtual callはBとして)解決されてました。

# 実装としては、vtableポインタが構築中のクラスのものになってるわけですが

YuO [E-Mail] 2004/04/05(月) 20:13:50
> >コンストラクタ/デストラクタ中では,仮想関数も静的に解決されます。
> 静的に解決されるというか、その時点のクラスとして解決されるのでは?

そちらの方が正しいですね。

コンストラクタやデストラクタから,
直接仮想関数を呼び出した時のことのみを念頭に書いたので,
上記のような表現をしてしまいました。


> 実装依存?

ちゃんと定められていますよ。その時点のクラスでよいです。
一応標準を引用しておきます。
ISO/IEC 14882:1998 12.7 Construction and destruction 段落3
>  When a virtual function is called directly or indirectly from a constructor
> (including from the meminitializer for a data member) or from a destructor,
> and the object to which the call applies is the object under construction or
> destruction, the function called is the one defined in the constructor or
> destructor's own class or in one of its bases, but not a function overriding
> it in a class derived from the constructor or destructor’s class, or
> overriding it in one of the other base classes of the most derived object.

古いスレッドには追加発言できません。