2013-03-14 32 views
15

「我相信有相同題目的數十個問題,其中很多都是重複的,我也可能是重複的,但我找不到任何東西,所以我儘量使它非常簡潔。如何用C++中的引用替換指針?

我有一個這樣的層次:

class Shape { 
public: 
    virtual void virtualfunc() { std::cout << "In shape\n"; } 
}; 

class Circle: public Shape { 
public: 
    void virtualfunc() { std::cout << "In Circle\n"; }; 
}; 

,當我使用的類與指針的幫助下,該功能被稱爲如我所料:

int main() { 
    Shape shape_instance; 
    Shape* ref_shape = &shape_instance ; 
    Circle circle_instance; 
    Circle* ref_circle = &circle_instance; 

    ref_shape = dynamic_cast<Shape*> (ref_circle); 
    ref_shape->virtualfunc(); 
} 

這裏的程序調用virtualfunc()的派生類,結果很自然:In Circle

現在,我想擺脫指針,而不是使用引用,並且得到相同的結果。所以我做瑣碎的修改main()看起來像這樣:

int main() { 
    Shape shape_instance; 
    Shape& ref_shape = shape_instance; 
    Circle circle_instance; 
    Circle& ref_circle = circle_instance; 

    ref_shape = dynamic_cast<Shape&>(ref_circle); 
    ref_shape.virtualfunc(); 
} 

但這一次,程序調用基類的virtualfunc(),其結果是:In Shape

,如果你讓我知道我很欣賞這我缺少的引用的概念以及如何更改main()中的引用以獲得指針版本中的結果。

謝謝

+0

你爲什麼又在這條線形狀和ref_shape = dynamic_cast的(ref_circle)宣佈ref_shape ;? – taocp 2013-03-14 03:56:11

+0

對不起,打字錯誤。我將只編輯 – rahman 2013-03-14 03:57:15

+1

沒有必要對基礎進行'dynamic_cast',這是一個隱式轉換。 – 2013-03-14 04:09:48

回答

18

參考文獻無法重新設定。在初始化初始化引用後,它將成爲引用對象的別名,並且無法與引用對象區分開來。後者的分配:

ref_shape = dynamic_cast<Shape&>(ref_circle); 

真正含義是:

shape_instance = dynamic_cast<Shape&>(ref_circle); 

可以,在另一方面,結合新的參照對象(你不需要dynamic_cast,從轉換引用來源的引用到基地是隱含的):

Shape & another_ref = ref_circle; 
another_ref.virtualfunc();   // Dispatches to Circle::virtualfunc 
+1

+1。這也是第一個解釋這個問題的答案:http://ideone.com/8GJ5W5 – Carl 2013-03-14 04:14:48

+0

@David謝謝。這也是正確的 – rahman 2013-03-14 04:17:24

1

如果我理解你想達到/節目(即動態虛擬函數結合)正確的東西,也許這個代碼將有助於:

#include <iostream> 
using namespace std; 

class Shape { 
    public: 
    virtual void virtualfunc() { std::cout << "In shape\n"; } 
}; 

class Circle: public Shape { 
    public: 
    void virtualfunc() { std::cout << "In Circle\n"; }; 
}; 

int main() { 
    Circle circle_instance; 

    // don't care what kind of Shape 
    Shape &someShape = circle_instance; 

    someShape.virtualfunc(); 
} 

在這裏你可以看到someShape可以綁定到Shape或任何派生類,虛擬函數將在實際的動態類型上調用。這將打印In Circle。證明:http://ideone.com/A1UvrR

沒有必要對dynamic_cast

+0

對不起,這是一個錯字。我做了修改。請看一看。謝謝 – rahman 2013-03-14 03:58:43

+0

@rahman看編輯 – 2013-03-14 04:01:53

+0

這就是讓我困惑的地方。當我分配一個圓圈(通過動態轉換)時,我期望調用圓方法(就像它在指針版本中那樣),爲什麼這不起作用? – rahman 2013-03-14 04:04:32

4

你應該做到以下幾點:

#include <iostream> 

class Shape { 
    public: 
    virtual void virtualfunc() { std::cout << "In shape\n"; } 
}; 

class Circle: public Shape { 
    public: 
    void virtualfunc() { std::cout << "In Circle\n"; }; 
}; 

int main() { 
    Shape shape_instance; 
    //Shape& ref_shape = shape_instance; 
    Circle circle_instance; 
    Circle& ref_circle = circle_instance; 

    Shape& ref_shape = dynamic_cast<Shape&>(ref_circle); 
    ref_shape.virtualfunc(); 
} 

它如你預期輸出的圈子。

+0

是的,我很抱歉。我糾正了錯誤。請看看。謝謝 – rahman 2013-03-14 04:01:47

+0

@rahman沒問題。 – taocp 2013-03-14 04:04:37

+0

不錯。但爲什麼?我能看到的是ref_shape調用了第一個分配給它的對象的虛函數,這是一個正確的解釋嗎? – rahman 2013-03-14 04:12:38

6

這是您的Circle變成Shape的地方。

ref_shape = dynamic_cast<Shape&>(ref_circle); 
//  ^here 
ref_shape.virtualfunc(); 

ref_shape已被定義爲對shape_instance的參考。

你是不是複製引用本身,因爲引用不能被重新分配。您正在將實際對象複製到一個Shape對象。它存儲在shape_instance中。

您可以通過嘗試此代碼來驗證。它將打印In Circle

dynamic_cast<Shape&>(ref_circle).virtualfunc(); 
+1

@rahman請注意,如果我正確理解您要做的事情,則不需要在您的情況下使用'dynamic_cast'。 – 2013-03-14 04:17:44

+0

@JorgeIsraelPeña你是對的 – rahman 2013-03-14 04:19:47