2014-01-22 31 views
0

鑑於基類和派生類如下:爲什麼動態綁定的行爲不如預期?

基礎:

class AA 
{ 
public: 
    AA() = default; 
    virtual void print() const { std::cout << aa << "\n";} 

private: 
    std::string aa = "AA"; 
}; 

派生:

class BB : public AA 
{ 
public: 
    BB() = default; 
    virtual void print() const override {std::cout << bb << "\n"; } 

private: 
    std::string bb = "BB"; 
}; 

第一次嘗試:

int main() 
{ 
    AA aa; BB bb; 
    AA& //r = aa; r.print(); 

    r = bb; 
    r.print(); 

    return 0; 
} 

結果是準確我所期望的:

BB 
Press <RETURN> to close this window... 

但第二次嘗試時//除去:

int main() 
{ 
    AA aa; BB bb; 
    AA& r = aa; r.print(); 

    r = bb; 
    r.print(); 
//!^^^^^^^^^^--why wasn't the print in derived class called? 
    return 0; 
} 

輸出爲:

AA 
AA 
Press <RETURN> to close this window... 

如上評論的,爲什麼沒有在派生類中定義的print調用時執行第二個r.print()

回答

3

因爲表達式r = bb完全等同於aa = bb。賦值運算符僅將AA類已知的bb的部分複製到aa對象中。

換句話說,在作業後,r仍指向aa,這是AA的一個實例。它確實從不是指向任何意義上的BB實例。

引用永遠不會改變它所引用的對象,因此預期的行爲不能通過引用來實現。爲了讓您正在尋找的多態性,你沉思使用指針:

AA* p = &aa; 
p->print(); 

p = &bb; 
p->print(); 
+0

因此,實際上該語句'R = bb'已經改變通過複製子aa'的'值 - 對象的對象'bb'給它,不是嗎? –

+0

我不確定我是否遵循「對象主題」術語,但是:'r = bb'只是運行'aa.AA :: operator =(bb)',然後將'AA'部分複製'bb'轉換成'AA'。 – user4815162342

+0

抱歉我的愚蠢的拼寫,我應該寫作subobject ..並不知道爲什麼我不能在你的名字user4815162342 .. –

1

正因爲如此:

r = bb; 

上述聲明不綁定(重新綁定?)參考rbb。相反,它將bbAA部分複製到aa,這是r引用的對象。

爲了檢驗上述要求,這裏是一個例子:http://coliru.stacked-crooked.com/a/00d20990fe0ddd26

+0

http://coliru.stacked-crooked.com/ - 這看起來挺方便的男人! –

+1

@Alan。W雖然在[C++ wiki頁面](http://stackoverflow.com/tags/c%2b%2b/info)中可以找到更多內容,但它在[tag:C++]中是相當「標準」的在線編譯器。 –