Considérez cet exemple:
#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?
}
Ici, vous pouvez voir que struct E
la classe de base vide (qui fait 1 octet de large) utilise le même stockage que le pointeur vtable, comme prévu.
Mais pour struct F
, qui a une base vide en double, cela ne se produit pas. Qu'est-ce qui cause cela?
J'obtiens le même résultat sur GCC, Clang et MSVC. Les résultats ci-dessus sont donc pour x64 sizeof(void *) == 8
.
Fait intéressant, pour struct G : A, B {void *ptr;};
GCC et Clang, effectuez EBO (la taille est de 8), mais pas MSVC (la taille est de 16).
C
et F
? Après tout, 2 * sizeof(void*) == 16
sur x86_64 comme vous l'avez dit. Le compilateur ne peut pas entièrement optimiser (comme l'a dit Story Teller) et ne le fait pas.
A
, hérité via B
, n'est pas accessible. C'est bon. Ce n'est que si vous essayez réellement d'y accéder, comme dans votre exemple, que vous obtenez une erreur.
C
(qui héritent deA
,B
) vous obtenez un résultat différent de héritant formeA
etB
directement