仮想継承
C++ の場合、同じクラスを継承する場合に明示的に virtual 修飾することではじめて仮想継承が有効になる。
クラス A を継承するクラス B と C があって、これらふたつを多重継承するクラス D において、基底クラス A を唯一にしたい…次のような継承関係を実現したい時に virtual キーワードを使う。
A / \ / \ B C \ / \ / D
virtual キーワードを指定する場所がわかりにくいとおもうので、上述の継承木を実現する際のコード断片を次に示す。
#include <iostream> struct A { int v_a; }; struct B : virtual A { int v_b; }; struct C : virtual A { int v_c; }; struct D : B, C { int v_d; }; int main() { D o; std::cout << &static_cast<A&>(o) << ", " << &static_cast<A&>(o).v_a << std::endl; std::cout << &static_cast<B&>(o) << ", " << &static_cast<B&>(o).v_a << std::endl; std::cout << &static_cast<C&>(o) << ", " << &static_cast<C&>(o).v_a << std::endl; std::cout << &static_cast<D&>(o) << ", " << &static_cast<D&>(o).v_a << std::endl; return 0; }
これをコンパイル・リンクして実行すると結果は次のようになる:
> make poly && ./poly
g++ poly.cc -o poly
0x7fff5fbffa80, 0x7fff5fbffa80
0x7fff5fbffa60, 0x7fff5fbffa80
0x7fff5fbffa70, 0x7fff5fbffa80
0x7fff5fbffa60, 0x7fff5fbffa80
D のインスタンス o をそれぞれ A, B, C, D にキャストして、そのオブジェクトとメンバー変数 v_a のアドレスを表示している。どのクラスにキャストしてもメンバー変数 v_a の実体は同じアドレスにある…これが仮想継承である。