Я знаю, что структура памяти множественного наследования не определена, поэтому мне не следует полагаться на нее. Однако могу ли я полагаться на него в особом случае. То есть класс имеет только один «настоящий» суперкласс. Все остальные являются «пустыми классами», то есть классами, у которых нет ни полей, ни виртуальных методов (, т. е. они имеют только не -виртуальные методы ). В этом случае эти дополнительные классы не должны ничего добавлять к структуре памяти класса. (Точнее, в формулировке C++11 класс имеет стандартный -макет)
Могу ли я сделать вывод, что все суперклассы не будут иметь смещения? Например.:
#include <iostream>
class X{
int a;
int b;
};
class I{};
class J{};
class Y : public I, public X, public J{};
int main(){
Y* y = new Y();
X* x = y;
I* i = y;
J* j = y;
std::cout << sizeof(Y) << std::endl
<< y << std::endl
<< x << std::endl
<< i << std::endl
<< j << std::endl;
}
Здесь Y
— это класс, а X
— единственный реальный базовый класс. Вывод программы (при компиляции на Linux с g++4.6 )выглядит следующим образом:
8
0x233f010
0x233f010
0x233f010
0x233f010
Как я понял, регулировки указателя нет. Но является ли эта реализация специфичной или я могу на нее положиться. То есть, если я получаю объект типаI
(и я знаю, что существуют только эти классы ), могу ли я использовать reinterpret_cast
, чтобы привести его к X
?
Я надеюсь, что смогу на это положиться, потому что в спецификации сказано, что размер объекта должен быть не менее байта. Поэтому компилятор не может выбрать другой макет. Если бы I
и J
располагались позади членов X
,тогда их размер будет равен нулю (, потому что у них нет членов ). Поэтому единственный разумный выбор — выровнять все суперклассы без смещения.
Я прав, или я играю с огнем, если использую здесь переинтерпретировать _с I
на X
?