Рассмотрим этот пример:
#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?
}
Здесь вы можете видеть, что для struct Eпустого базового класса (размером 1 байт) используется то же хранилище, что и для указателя vtable, как и ожидалось.
Но для struct F, у которого есть дублирующаяся пустая база, этого не происходит. Что вызывает это?
Я получаю тот же результат на GCC, Clang и MSVC. Выше приведены результаты для x64, поэтому sizeof(void *) == 8.
Интересно, что для struct G : A, B {void *ptr;};GCC и Clang действительно выполняется EBO (размер 8), но MSVC нет (размер 16).
Cи F? В конце концов, 2 * sizeof(void*) == 16на x86_64, как вы сказали. Компилятор не может полностью оптимизировать (как сказал Стори Теллер) и не делает этого.
A, унаследованный через B, не может быть доступен. Это хорошо. Только если вы действительно попытаетесь получить к нему доступ, как в вашем примере, вы получите ошибку.
C(которые наследуют отA,B) вы получите другой результат , чем наследование формыAиBнепосредственно