Теоретически, компилятор может размещать базовые классы по-разному. C ++ 03 §10 параграф 5 гласит:
Подобъект базового класса может иметь компоновку (3.7), отличную от компоновки наиболее производного объекта того же типа.
Как отмечал StackedCrooked , это может произойти, если компилятор добавляет заполнение в конец базового класса A
, когда он существует как собственный объект, но компилятор может не добавить это заполнение, когда Базовый класс. Это заставит A::clear()
перезаписать первые несколько байтов членов подкласса.
Однако на практике мне не удалось этого добиться ни с GCC, ни с Visual Studio 2008. Использование этого теста:
struct A
{
void clear() { memset(this, 0, sizeof(A)); }
int age;
char type;
};
struct B : public A
{
char x;
};
int main(void)
{
B b;
printf("%d %d %d\n", sizeof(A), sizeof(B), ((char*)&b.x - (char*)&b));
b.x = 3;
b.clear();
printf("%d\n", b.x);
return 0;
}
И изменение A
, B
или обоих для «упаковки» (с #pragma pack
в VS и __attribute__((packed))
в GCC), я не мог ' b.x
может быть перезаписано в любом случае. Оптимизации были включены. 3 значения, напечатанные для размеров / смещений, всегда были 8/12/8, 8/9/8 или 5/6/5.