2011-11-22 61 views
1

以下代碼:參考變量和的傳承

#include <stdio.h> 
class Parent 
{ 
public: 
    virtual void func() {printf("Parent\n");} 
}; 

class Child1 : public Parent 
{ 
    virtual void func() {printf("Child1\n");} 
}; 

class Child2 : public Parent 
{ 
    virtual void func() {printf("Child2\n");} 
}; 

int main(int argc, char* argv[]) 
{ 
    Parent & obj = Child1(); 
    obj.func(); 
    obj = Child2(); 
    obj.func(); 
    return 0; 
} 

產生以下結果:

expected: Child1 Child2. 

actual: Child1 Child1. 

(編上VS2010)

我想的是,vptr的沒有被分配改變。有沒有辦法讓它重新創建(除了使用指向Parent的指針並使用new賦值)?

感謝

+6

參考資料不能被重新安排!此外臨時不能綁定到非常量引用。你的代碼不合格 –

+2

爲什麼_would_你首先要做這個參考?如果你改變'obj',使它成爲一個對象或一個指針。 – leftaroundabout

+1

這甚至不會編譯!請在這裏發佈一些真實的代碼。 –

回答

3

你調用obj中的默認的賦值運算符,這仍然是類型Child1,具有類型CHILD2的參數。該對象本身仍然是Child1類型。您可以通過在所有3個類上實施operator =並在其中插入打印語句來驗證此情況。

+0

謝謝。有沒有在ref var上使用多態的方法? – OSH

+0

@OrenS。你正在使用多態。這就是爲什麼對Child1 :: func的調用有效。但是你沒有一個Child2類型的對象,但是Child1。 –

+3

您可以執行** rebindable **多態的唯一方法是使用指針。爲了顯而易見的原因,我建議使用智能指針。 – moshbear

1

參考文獻無法重新設置 - 它們在整個生命週期中都指向同一個對象。如果你想要改變它引用的對象,那麼你需要使用[smart]指針而不是引用。

您在這裏做的是slicingChild2的實例,方法是將其分配給Child1的實例。

1
Parent & obj = Child1(); 

您可以創建對Child1類型的對象的引用。這就好比說現在

Child1 c1; 
Parent& obj = c1; 

obj僅僅是c1一個不同的名稱,這是Child1類型的對象。現在

obj = Child2(); 
obj.func(); 

,這好像是說

c1 = Child2(); 
c1.func(); 

所以你看,你仍然Child1類型的對象上調用func

0

你在做什麼應該會在編譯時出錯。您不能將一個臨時變量(由Child2()創建)分配給引用變量。您必須在Child2之前創建一個實例,並將該變量分配給尊敬。

+0

我的編譯器不同意... – OSH

+0

@OrenS。我錯誤的錯誤,它實際上是爲'Parent&obj = Child1();'行我得到一個錯誤。 –

+1

'g ++'不能編譯這個,但是當然你可以總是創建一個'Child1'類型的變量並從那裏分配。令人着迷的是,VS2010首先將其編譯。 – hochl

1

C++中的兩個基本屬性:一旦創建對象,永遠不會改變它的類型 ,並且一旦初始化引用,引用總是指 相同的對象。

這裏發生的事情是,你調用編譯器提供 非虛operator=Parent,這是幾乎可以肯定不是你想要的 。然而,更一般地說,賦值和繼承並不是 可以很好地協同工作(正因爲你不能改變對象的類型)。大多數情況下,在使用繼承時,應禁止 分配(例如,繼承自boost::noncopyable)。它是 可能實現多態類的價值語義,使用 字母/信封成語,但它是一個沉重的解決方案,很少 適當。

(我想補充一點你的代碼不與C++編譯器編譯。你 初始化參照非const有暫時的,這是不合法的 C++允許這是微軟擴展)