Гарантии по адресу BaseClass в C ++?
-
24-09-2019 - |
Вопрос
В C struct, я гарантию, что:
struct Foo { ... };
struct Bar {
Foo foo;
...
}
Bar bar;
assert(&bar == &(bar.foo));
Теперь, в C ++, если у меня есть:
class Foo { ... };
class Bar: public Foo, public Other crap ... {
...
}
Bar bar;
assert(&bar == (Foo*) (&bar)); // is this guaranteed?
Если это так, вы можете дать мне ссылку (например, «язык программирования C ++, страница XYZ»)?
Спасибо!
Решение
Там нет гарантии. Из стандарта C ++ 03 (10/3, класс. Индер):
Порядок, в котором подборки базового класса выделяются в наиболее производном объекте (1.8), не указан.
Другие советы
Хотя макет для базовых классов не гарантировано Таким образом, вы, кажется, думаете (и даже если есть больше гарантий для членов), это гарантируется:
Bar bar;
assert(&bar == (Foo*) (&bar));
Потому что литые используются Static_Cast (за 5,4), которые будут конвертировать &bar
Правильно, и сравнение у указателя к базе и указывающему к получению будет конвертировать аналогично.
Это, однако, не будет гарантировано не гарантировано:
Bar bar;
void* p1 = &bar;
void* p2 = (Foo*)&bar;
assert(p1 == p2); // not guaranteed
Я не представляю, что это будет, я не знаю, почему это должно быть.
У меня связанный вопрос.
Если у вас есть алмазное наследование:
class Base(){ virtual void AFunc(){} };
class A:Base{};
class B:Base{void AFunc(){} }
class Test:A,B{};
Base * b = (Base*)new Test;
b->AFunc();
Предположим, что структура памяти является основой: A: B: тест,
Примечание. В точке вызова все компиляторы знают, является адресом начала объекта, а afunc ожидает быть относительным к началу объекта B, эти два адреса не будут одинаковыми! Итак, как это работает?
Как и если B имел тип B, два адреса будут одинаковыми ...