2013-10-09 38 views
4

我正在學習C++形式在C++ V1中思考。我遇到了一個演示繼承的例子。這裏去吧爲什麼'&'會改變對象的行爲?

#include <iostream> 

class Instrument{ 
public: 
    virtual void play(){ 
     std::cout<<"instrument::play()"; 
    } 
}; 

class Wind: public Instrument{ 
public: 
    void play(){ 
     std::cout<<"Wind::play()"; 
    } 
}; 

void tune(Instrument& i){ 
    i.play(); 
} 
int _tmain(int argc, _TCHAR* argv[]) 
{ 
    Wind flute; 
    tune(flute); 
    return 0; 
} 

這在控制檯上輸出Wind::play()

但是,如果我改變方法,「調整」到

void tune(Instrument i){ 
    i.play(); 
} 

輸出將讓笛子的引用,而不是通過副本instrument::play()

由於「&」添加,爲什麼程序輸出instrument::play()而不是Wind::play()

+2

http://stackoverflow.com/a/274634/2101267 –

回答

7

C++中對象表達式的多態行爲由其動態類型爲確定。

  • Instrument &i類型的參考附加到Wind類型的對象,通過i稱爲動態對象的類型是保存。即即使i被聲明爲Instrument,但實際上指的是類型爲Wind的實際對象。這就是爲什麼i繼續表現爲Wind。如果你參考某些對象與指針也是如此。

    在形式語言上來講,這意味着表達i靜態類型Instrument,但動態類型如果同樣的表達是Wind。由於這個原因,i行爲多態爲Wind

  • 同時,當你分配(或初始化)的對象Instrument iWind類型的值,則創建Instrument類型的獨立的獨立對象i。這個對象的類型是Instrument。因此,獨立副本i在所有多態環境中的行爲將爲Instrument

    再次,在形式語言來說,它意味着在該情況下,兩個靜態類型動態型表達iInstrument。由於這個原因,i行爲多態爲Instrument

在C++語言爲「保留」的動態類型的物體的唯一方法是與指針或引用對象。 「引用」是這裏的關鍵詞:你不創建新的對象,而是參考已經存在的對象。那些現有的對象繼續按照它們的本地類型行事。類型爲Wind的對象繼續表現爲Wind類型的對象。 (請注意,這適用於多態性行爲只,如要虛擬函數調用是如何解決的。)

但每當你創建一個對象的獨立副本(而不是原來的)該副本獲得自己的生命,擁有自己的類型和相關屬性。 Instrument類型的獨立副本與原始Wind對象沒有任何關係。它沒有記憶它是作爲一個Wind對象的副本而誕生的。它的行爲如同Instrument

-2

調用Instrument::play函數的原因是因爲當您傳遞副本時,它實際上是您傳遞的對象的Instrument部分,因爲您的對象是slice

+1

這在技術上是正確的,但完全沒有幫助,並沒有真正解釋OP的混淆。 – Puppy

+0

@DeadMG我很快就回答,仍然在寫它。並刪除了其他(不需要的)信息。 –

17

因爲副本獲取傳遞的類型爲Instrument,不會打字Wind,因爲Instrument是該函數需要的類型。這被稱爲「切片」。

+0

這真的是最正確的答案 - 「儀器」只能是「儀器」。 – Puppy

+0

很好,在6分鐘內有10個選票。 – jodag

3

這就是所謂的「slicing」的問題。當您將Wind複製到Instrument時,它將變爲Instrument

0

void tune(Instrument i){ 
    i.play(); 
} 

您創建一個新的實例,如果Instrument對象,而Instrument對象將打印instrument::play

當您使用的參考運營商&你提到了是的現有對象Wind類型。

相關問題