Xem xét ví dụ này:
#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?
}
Ở đây bạn có thể thấy rằng đối với struct Elớp cơ sở trống (lớn 1 byte) sử dụng cùng một bộ lưu trữ như con trỏ vtable, như mong đợi.
Nhưng đối với struct Fmột cơ sở trống trùng lặp, điều này không xảy ra. Điều gì gây ra điều này?
Tôi nhận được kết quả tương tự trên GCC, Clang và MSVC. Các kết quả trên là cho x64, vì vậy sizeof(void *) == 8.
Thật thú vị, đối với struct G : A, B {void *ptr;};GCC và Clang thực hiện EBO (kích thước là 8), nhưng MSVC thì không (kích thước là 16).
Cvà F? Sau tất cả, 2 * sizeof(void*) == 16trên x86_64 như bạn đã nói. Trình biên dịch không thể tối ưu hóa hoàn toàn (như Story Teller đã nói) và vì vậy không.
A, được kế thừa qua B, không thể truy cập được. Điều đó là tốt. Chỉ khi bạn thực sự cố gắng truy cập nó, như trong ví dụ của bạn, bạn sẽ gặp lỗi.
C(kế thừa từ )A,Bbạn sẽ nhận được kết quả khác với hình thức kế thừaAvàBtrực tiếp