- 489 名前:デフォルトの名無しさん [2005/11/07(月) 11:50:43 ]
- ポインタの静的型と、仮想関数の振る舞いについて教えてください。
struct A { virtual void f(); }; struct B { virtual void f(); }; struct C: public A, public B {}; C* pc = new C; pc->f(); // (1) A::f() と B::f() のどちらか分からないのでコンパイルエラー A* pa = pc; pa->f(); // (2) A::f() がコールされる B* pb = pc; pb->f(); // (3) B::f() がコールされる struct D: public A, public B { virtual void f(); }; D* pd = new D; pd->f(); // (4) D::f() がコールされる pa = pd; pa->f(); // (5) D::f() がコールされる pb = pd; pb->f(); // (6) D::f() がコールされる struct C の仮想関数テーブルの f() のエントリはどうなっているのでしょう? 派生クラスが仮想関数をオーバライドしない場合、このエントリは基底クラスの 関数ポインタがそのままコピーされると思います。しかし、A::f と B::f のど ちらを採用すべきかコンパイル時に決定できないはずです。 ところが上記(2)のように、動的型が struct C であっても、静的型を struct A とするとコンパイルが通り A::f() がコールされます。動的型の struct C の仮 想関数テーブルの f() のエントリは決定できていないはずなのに、何故 (2)(3) のような呼び分けができるのでしょう? 実際 struct D のように f() をオーバライドすると、静的型に関係なく動的型 の仮想関数がコールされるので、f() のエントリは1つだと思うのですが。 どういうカラクリになっているのでしょう?
|

|