A herança múltipla torna isso falso.
Isso não está totalmente correto. Considere este exemplo:
struct A {};
struct B : A {};
struct C : A {};
struct D : B, C {};
Ao criar uma instância de D
, B
e C
são instanciados, cada um com sua respectiva instância de A
. No entanto, não haveria problema se a instância de D
tivesse o mesmo endereço de sua instância de B
e sua respectiva instância de A
. Embora não seja necessário, é exatamente isso que acontece ao compilar com clang 11
e 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
A herança virtual também torna isso falso
Vamos considerar uma versão modificada do exemplo acima:
struct A {};
struct B : virtual A {};
struct C : virtual A {};
struct D : B, C {};
O uso do virtual
especificador de função geralmente é usado para evitar chamadas de função ambíguas. Portanto, ao usar virtual
herança, as instâncias B
e C
devem criar uma A
instância comum . Ao instanciar D
, obtemos os seguintes endereços:
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)
O código a seguir está correto
Aqui não há razão para usar reinterpret_cast
, ainda mais, isso resulta em um comportamento indefinido. Use em static_cast
vez disso:
A* pA = static_cast<A*>(pB);
Ambos os modelos se comportam de maneira diferente neste exemplo. O reinterpret_cast
reinterpretará pB
como um ponteiro para A
, mas o ponteiro pA
pode apontar para um endereço diferente, como no exemplo acima (C vs A). O ponteiro será convertido corretamente se você usar static_cast
.
reinterpret_cast
com classes é sempre suspeito (exceto da classe paravoid*
e volta para a mesma classe).