Гарантии по адресу baseclass в C++?
В структурах C я гарантирую, что:
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")?
Спасибо!
3 ответа
Там нет гарантии. Из стандарта C++03 (10/3, class.derived):
Порядок, в котором подобъекты базового класса размещаются в наиболее производном объекте (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();
давайте предположим, что структура памяти является Base:A:B:Test,
обратите внимание, что в момент вызова компилятор знает только адрес начала объекта, и AFunc ожидает, что он будет относительно начала объекта B, эти два адреса не будут одинаковыми! Итак, как это работает?
как если бы b был типа B, два адреса были бы одинаковыми...