Ответ 1
Причина в том, что стандартные типы макетов эффективно определяют "пустую оптимизацию базового класса", когда базовые классы без каких-либо элементов данных не занимают места и имеют тот же адрес, что и первый член данных (если он есть) производного класса.
Однако попытка сделать это, когда базовый класс имеет тот же тип, что и первый член данных, нарушает модель памяти С++, которая требует, чтобы разные объекты одного и того же типа имели разные адреса.
Из ISO/IEC 14882: 2011 1.8 [intro.object]/6:
Два объекта, которые не являются битовыми полями, могут иметь один и тот же адрес, если один является подобъектом другого, или если хотя бы один является подобъектом базового класса с нулевым размером и они имеют разные типы; в противном случае они должны иметь разные адреса.
эффективно передавая пустой базовый класс, 9.2 [class.mem]/20:
Указатель на объект структуры стандартного макета, соответствующим образом преобразованный с помощью
reinterpret_cast
, указывает на его начальный член (или если этот элемент является битовым полем, а затем блоку, в котором он находится) и наоборот.
Было бы невозможно, чтобы следующие типы (Type1
и Type2
) были совместимы с макетами (хотя в противном случае они были бы стандартными классами макета) без этого ограничения.
struct S1 {};
struct S2 {};
struct Type1 : S1 {
S1 s;
int k;
};
struct Type2 : S1 {
S2 s;
int m;
};