多重継承はそれを真実にしません。
それは完全に正しいわけではありません。この例を考えてみましょう:
struct A {};
struct B : A {};
struct C : A {};
struct D : B, C {};
のインスタンスを作成するときD
、B
およびC
はそれぞれのそれぞれのインスタンスでインスタンス化されますA
。ただし、のインスタンスがのD
インスタンスB
とのそれぞれのインスタンスのアドレスが同じであれば問題はありませんA
。必須ではありませんが、clang 11
andでコンパイルすると、これが正確に起こり gcc 10
ます。
D: 0x7fffe08b4758 // address of instance of D
B: 0x7fffe08b4758 and A: 0x7fffe08b4758 // same address for B and A
C: 0x7fffe08b4760 and A: 0x7fffe08b4760 // other address for C and A
仮想継承もそれを真実にしませんか
上記の例の修正版を考えてみましょう:
struct A {};
struct B : virtual A {};
struct C : virtual A {};
struct D : B, C {};
virtual
関数指定子の使用は通常、あいまいな関数呼び出しを回避するために使用されます。したがって、virtual
継承を使用する場合はB
、C
インスタンスとインスタンスの両方で共通のA
インスタンスを作成する必要があります。をインスタンス化D
すると、次のアドレスが取得されます。
D: 0x7ffc164eefd0
B: 0x7ffc164eefd0 and A: 0x7ffc164eefd0 // again, address of A and B = address of D
C: 0x7ffc164eefd8 and A: 0x7ffc164eefd0 // A has the same address as before (common instance)
次のコードは正しいですか
ここでを使用する理由はありませんreinterpret_cast
。さらに、未定義の動作が発生します。static_cast
代わりに使用:
A* pA = static_cast<A*>(pB);
この例では、両方のキャストの動作が異なります。reinterpret_cast
再解釈されますpB
へのポインタとしてA
、しかしポインタはpA
上記の例(A対C)のように、異なるアドレスを指すことができます。を使用すると、ポインタは正しくアップキャストされますstatic_cast
。
reinterpret_cast
クラスの場合は常に怪しげです(クラスからvoid*
、および同じクラスに戻ることを除く)。