ลองพิจารณาตัวอย่างนี้:
#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โดยตรง