Наследование макета памяти

Рассмотрим следующие две структуры:

struct A
{
// A bunch of standard layout data
};

struct B:public A
{
// Other data
};

И объект

B foo;

Предположим, что sizeof (A) не отличается между компиляторами, упаковка одинакова, и B не добавляет никаких виртуальных методов, поэтому члены A будут иметь один и тот же адрес по отношению к &foo при компиляции с использованием gcc или msvc для платформы Windows x86 или x86-64?

РЕДАКТИРОВАТЬ: Я понял, что лучший способ реализовать наследование, это поместить A перед B. В противном случае, upcast потребует смещения указателя this на sizeof (B), что глупо. По крайней мере, GCC помещает содержание B после содержания A.

3

Решение

Архитектура x86_64 является проблемой, GCC и MSVC выбрали разные модели памяти. GCC — это LP64, MSVC — это LLP64. Другими словами, долго тип — 64-битный в GCC, 32-битный в MSVC.

«Тот же адрес» довольно неоднозначен в этом вопросе, но, очевидно, у вас возникнет проблема, если A и B не скомпилированы одним и тем же компилятором. В этом случае, возможно, другая упаковка также будет проблемой. Интерполяция из той же неоднозначности, если B содержит какие-либо виртуальные элементы, а A нет, то расположение A и B несовместимо. B будет вставлен указатель v-таблицы.

2

Другие решения

Ганс все правильно объяснил. Общий ответ НЕТ. Это не будет работать из коробки для любого класса / компилятора и т. Д.

Тем не менее. C ++ имеет такие функции, как #pragma packзапись выравнивания в классе и т. д. Все эти вещи предназначены для создания требуемой или предопределенной схемы памяти. Если вы будете осторожно использовать их (возможно, с некоторыми #ifdefs также), у вас будет совместимость, которую вы хотите. Это использовалось в тоннах проектов, и это работало.

Но все же вам придется тщательно проверять макеты для каждого компилятора, который вы используете.

1