2013-02-08 105 views
11

在項目27「有效的C++」的(第3版,第118頁),斯科特Meyers表示:派生類對象有多個地址?

class Base { ... }; 
class Derived: public Base { ... }; 
Derived d; 
Base *pb = &d; 

這裏我們只是創建一個基類指針指向一個派生類對象,但有時這兩個指針不會一樣。當出現這種情況時,在運行時將偏移量應用到Derived*指針,以獲取正確的Base*指針值。

這最後一個實施例表明,一個單一的對象(例如,Derived類型的對象)可能具有多個地址(例如,當在由Derived*指針指向由Base*指針和其地址指向它的地址) 。

這裏有點讓人費解。我知道指向基類的指針可以在運行時指向派生類的對象,這稱爲多態或動態綁定。但派生類對象在內存中是否真的有多個地址?

猜猜我有一些誤解在這裏。有人可以澄清一下嗎?也許這與C++編譯器中如何實現多態性有關。

回答

13

試試看:

class B1 
{ 
    int i; 
}; 

class B2 
{ 
    int i; 
}; 

class D : public B1, public B2 
{ 
    int i; 
}; 

int 
main() 
{ 
    D aD; 
    std::cout << &aD << std::endl; 
    std::cout << static_cast<B1*>(&aD) << std::endl; 
    std::cout << static_cast<B2*>(&aD) << std::endl; 
    return 0; 
} 

還有爲B1子對象沒有可能的方式有相同的 地址作爲B2子對象。

4

一個對象只有一個地址;這就是它在內存中的位置。當您創建一個指向基地子對象你得到的子對象的地址,而不必是相同的包含它的對象的地址。一個更簡單的例子:

struct S { 
    int i; 
    int j; 
}; 

S s; 

s的地址將是從s.j地址不同。

類似地,基地子對象的地址不必是相同的派生對象的地址。使用單一繼承通常是,但是當多重繼承發揮作用並且忽略空的基類時,至多其中一個基類子對象可以具有與派生對象相同的地址。因此,當你將一個指向派生對象的指針轉換爲指向它的一個基地址的指針時,你不一定會獲得與派生對象地址相同的值。

+0

「與單繼承它通常是」 - 你能想到的任何情況下,它*不會*? – us2012 2013-02-08 16:10:04

+4

@ us2012:非多態基類,多態派生類,在派生類中偏移量0處添加的vtable指針,後跟基類。 – MSalters 2013-02-08 16:26:58

+0

@ MSalters很好!謝謝。 – us2012 2013-02-08 16:27:54