あるクラス「A」があって、その派生クラス「B」があるとします。
クラス「B」が破棄されるとき「B::~B()」→「A::~A()」の順番でデストラクタが呼ばれます。
「A::~A」のときにクラス「B」の仮想メソッド(クラス「A」で定義されクラス「B」にオーバー
ライドされている)を呼び出そうとした時、クラス「A」の仮想メソッドが呼ばれてしまいます。
これは「A::~A()」の時にクラス「B」は破棄されてしまっているということなのでしょうか?
開発環境:Win2000、VC++6.0、APIのみ
なんかよく分りませんが、クラスAを作って破棄している分にはクラスBは関係ありません。
動的に作成したクラスBのポインタをクラスAのポインタにキャストさせた後、
クラスAのポインタでdeleteしてみたら分ると思います。
> 「A::~A」のときにクラス「B」の仮想メソッド(クラス「A」で定義されクラス「B」
にオーバー
> ライドされている)を呼び出そうとした時、クラス「A」の仮想メソッ
ドが呼ばれてしまいます。
> これは「A::~A()」の時にクラス「B」は破棄されてしまっているということなのでしょ
うか?
そういうことです。
コンストラクタ/デストラクタ中では,仮想関数も静的に解決されます。
関連することでは,επιστημηさんがこんな記事を書いていますね。
http://www.s34.co.jp/cpptechdoc/article/sizeof/
やはりそういうものなのだったのですね。疑問も解決しました。
有難うございました。
>コンストラクタ/デストラクタ中では,仮想関数も静的に解決されます。
静的に解決されるというか、その時点のクラスとして解決されるのでは?
実装依存?
この辺のC++の仕様の詳細を把握してないですが、私が触ったいくつかのコンパイラでは
ctor/dtor中でのvirtual callは、構築途中の段階のクラスとして(= A-B-Cという継承
関係がある場合、Bのctor/dtor内でのvirtual callはBとして)解決されてました。
# 実装としては、vtableポインタが構築中のクラスのものになってるわけですが
> >コンストラクタ/デストラクタ中では,仮想関数も静的に解決されます。
> 静的に解決されるというか、その時点のクラスとして解決されるのでは?
そちらの方が正しいですね。
コンストラクタやデストラクタから,
直接仮想関数を呼び出した時のことのみを念頭に書いたので,
上記のような表現をしてしまいました。
> 実装依存?
ちゃんと定められていますよ。その時点のクラスでよいです。
一応標準を引用しておきます。
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.