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 Ela 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).
Cet F? Après tout, 2 * sizeof(void*) == 16sur 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 formeAetBdirectement