Гарантии по адресу baseclass в C ++? - PullRequest
8 голосов
/ 31 января 2010

В структурах 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 ]

10 голосов
/ 31 января 2010

гарантии нет. Из стандарта C ++ 03 (10/3, class.derived):

Порядок, в котором подобъекты базового класса размещаются в наиболее производном объекте (1.8), не указан.

6 голосов
/ 31 января 2010

Несмотря на то, что макет для базовых классов не гарантирован в том виде, в котором вы, кажется, думаете (и хотя для членов есть больше гарантий), это гарантировано:

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
1 голос
/ 31 января 2010

Не думаю, что это будет, я не знаю, зачем это нужно.

У меня есть связанный вопрос.

если у вас есть наследство алмазов:

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: Test,

обратите внимание, что в момент вызова компилятор знает только адрес начала объекта, и AFunc ожидает, что он будет относительно начала объекта B, эти два адреса не будут одинаковыми! так как это работает?

как если бы b имел тип B, два адреса были бы одинаковыми ...

...