Considera questo esempio:
#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?
}
Qui puoi vedere che per struct Ela classe base vuota (che è grande 1 byte) usa la stessa memoria del puntatore vtable, come previsto.
Ma per struct F, che ha una base vuota duplicata, questo non accade. Cosa causa questo?
Ottengo lo stesso risultato su GCC, Clang e MSVC. I risultati sopra riportati sono per x64, quindi sizeof(void *) == 8.
È interessante notare che struct G : A, B {void *ptr;};GCC e Clang eseguono EBO (la dimensione è 8), ma MSVC no (la dimensione è 16).
Ce F? Dopotutto, 2 * sizeof(void*) == 16su x86_64 come hai detto. Il compilatore non può ottimizzare completamente (come ha detto Story Teller) e così non lo è.
A, ereditato Bda. Questo va bene. Solo se effettivamente provi ad accedervi, come nel tuo esempio, ricevi un errore.
C( da cui ereditano )A,Bsi ottengono risultati diversi rispetto all'ereditarietà della formaAeBdirettamente