【问题标题】:Guarantees on address of baseclass in C++?C++中基类地址的保证?
【发布时间】:2011-01-11 08:43:31
【问题描述】:

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

谢谢!

【问题讨论】:

    标签: c++ inheritance base-class object-address


    【解决方案1】:

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

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

    【讨论】:

    • 注意;谢谢。 :-) g++ 几乎让我相信这是有保证的。
    • 作为旁注,该标准对非 POD 类型的布局承诺很少 - 基本上只是非静态数据成员的地址顺序未被中间访问说明符分隔将匹配声明顺序(但仅在同一“访问说明符部分”内)。
    【解决方案2】:

    尽管基类的布局是 not guaranteed,就像您一直在想的那样(即使对成员有更多的保证),但这是有保证的:

    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
    

    【讨论】:

    • @Roger:关于static_cast 转换的一个很好的观点。
    【解决方案3】:

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

    我有一个相关的问题。

    如果你有钻石继承:

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

    【讨论】:

    • @matt:请提出一个新问题。
    • 这正是 5.4/5 中的示例(但存在其他可访问性问题)并且格式错误(需要编译器进行诊断)。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多