Множественное наследование не соответствует действительности.
Это не совсем правильно. Рассмотрим следующий пример:
struct A {};
struct B : A {};
struct C : A {};
struct D : B, C {};
При создании экземпляра D
создаются экземпляры B
и C
каждый со своим соответствующим экземпляром A
. Однако не было бы проблем, если бы экземпляр D
имел тот же адрес, что и его экземпляр B
, и соответствующий ему экземпляр A
. Хотя это и не обязательно, это именно то, что происходит при компиляции с clang 11
и 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
может указывать на другой адрес, как в примере выше (C против A). Указатель будет корректно активирован, если вы используете static_cast
.