8

在 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”)吗?

谢谢!

4

3 回答 3

10

没有任何保证。来自 C++03 标准(10/3,class.derived):

未指定在最派生对象 (1.8) 中分配基类子对象的顺序。

于 2010-01-31T06:28:14.960 回答
6

尽管基类的布局并不能以您似乎一直在想的方式得到保证(并且即使对成员有更多保证),但这是可以保证的:

Bar bar;
assert(&bar == (Foo*) (&bar));

因为强制转换使用将&bar正确转换的 static_cast(根据 5.4),并且指向基址的指针和指向派生的指针之间的比较将类似地转换。

但是,这不能保证:

Bar bar;
void* p1 = &bar;
void* p2 = (Foo*)&bar;
assert(p1 == p2); // not guaranteed
于 2010-01-31T06:37:33.977 回答
1

我不认为它会是,我不知道为什么会这样。

我有一个相关的问题。

如果您有钻石继承权:

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 类型,这两个地址将是相同的......

于 2010-01-31T06:33:09.100 回答