Betrachten Sie dieses Beispiel:
#include <iostream>
int main()
{
struct A {};
struct B : A {};
struct C : A, B {};
std::cout << sizeof(A) << '\n'; // 1
std::cout << sizeof(B) << '\n'; // 1
std::cout << sizeof(C) << '\n'; // 2, because of a duplicate base
struct E : A {virtual ~E() {}};
struct F : A, B {virtual ~F() {}};
std::cout << sizeof(E) << '\n'; // 8, the base overlaps the vtable pointer
std::cout << sizeof(F) << '\n'; // 16, but why?
}
Hier können Sie sehen, dass für struct Edie leere Basisklasse (die 1 Byte groß ist) erwartungsgemäß derselbe Speicher wie für den vtable-Zeiger verwendet wird.
Aber für struct F, die eine doppelte leere Basis hat, passiert dies nicht. Was verursacht das?
Ich erhalte das gleiche Ergebnis bei GCC, Clang und MSVC. Die obigen Ergebnisse gelten für x64 sizeof(void *) == 8.
Interessanterweise führen struct G : A, B {void *ptr;};GCC und Clang EBO durch (die Größe ist 8), MSVC jedoch nicht (die Größe ist 16).
Cund ergibt F? Immerhin 2 * sizeof(void*) == 16auf x86_64, wie Sie gesagt haben. Der Compiler kann nicht vollständig optimieren (wie Story Teller sagte) und tut dies auch nicht.
A, die über geerbt wurde B, nicht zugegriffen werden kann. Das ist gut. Nur wenn Sie tatsächlich versuchen, wie in Ihrem Beispiel darauf zuzugreifen, wird eine Fehlermeldung angezeigt.
C(die erben vonA,B) Sie anderes Ergebnis erhalten , als Form vererbenAundBdirekt