2010-01-31 33 views
8

在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「)?

謝謝!

回答

10

沒有保證。從C++ 03標準(10/3,class.derived):

未指定基類子對象在最大派生對象(1.8)中的分配順序。

+1

注意到;謝謝。 :-) g ++幾乎讓我相信這是有保證的。 – anon

+0

作爲一個側面說明,該標準對非POD類型的佈局承諾很少 - 基本上只是非靜態數據成員的地址順序未由介入訪問指定符分隔將與聲明順序相匹配(但僅限於相同的「訪問說明符部分」)。 –

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(); 

讓我們假設存儲結構是基礎:A:B:測試,在調用點

注意到,所有的編譯器知道是地址對象的開始,並且AFunc期望相對於B對象的開始,這兩個地址將不會相同!那麼它是怎樣工作的?

一樣,如果B爲B型,這兩個地址是相同的......

+0

@matt:請提出一個新問題。 – kennytm

+0

這正是5.4/5中的例子(但帶有額外的可訪問性問題),並且不合格(需要編譯器進行診斷)。 – 2010-01-31 06:41:47

6

即使佈局基類是在你似乎的方式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 
+0

@Roger:關於'static_cast'轉換的一個很好的觀點。 –