この例を考えてみましょう:
#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)。
Cand の導出から導入されたあいまいさから生じるのFでしょうか?結局のところ、2 * sizeof(void*) == 16あなたが言ったようにx86_64で。(Story Tellerが言ったように)コンパイラーは完全に最適化することはできません。
A、を介して継承された2番目のにはBアクセスできないことを警告するだけです。それは結構です。例のように実際にアクセスしようとした場合にのみ、エラーが発生します。
C(A、から継承する)から継承することで、BフォームAをB直接継承する場合とは異なる結果が得られます