2016-01-30 26 views
-1

在我的例子:C++ - 上溯造型和向下轉換

在向上轉型,應該不是第二d.print()調用印刷「基地」?

是不是「d」派生的對象上傳到基類對象?

而在向下轉換時,它有什麼優勢?

您能否以實際的方式解釋upcast和downcast?

#include <iostream> 
using namespace std; 

class Base { 
public: 
    void print() { cout << "base" << endl; } 
}; 

class Derived :public Base{ 
public: 
    void print() { cout << "derived" << endl; } 

}; 

void main() 
{ 
    // Upcasting 
    Base *pBase; 
    Derived d; 
    d.print(); 
    pBase = &d; 
    d.print(); 

    // Downcasting 
    Derived *pDerived; 
    Base *b; 
    pDerived = (Derived*)b; 
} 
+1

爲什麼你認爲'pBase'行應該改變'd.print();'的行爲?你的意思是詢問'pBase-> print();'? –

回答

1

你需要爲了使RTTI使用虛擬方法。

就你而言,由於你使用的是C++,你應該依賴更安全的轉換機制。所以,而不是(Derived*)b,你應該使用dynamic_cast<Derived*>(b)。這允許你確保你實際上擁有一個指向一個基類(接口)的對象的指針,該指針是通過鑄造一個Derived類型的對象而獲得的。 This page提供了進一步的解釋。

+0

@Downvoter:你願意評論嗎? –

3

上傳在C++中是隱含的,在處理虛擬調度時會用到很多。換句話說,您有一個指向Base的指針,您可以從中訪問整個層次類的公共接口,並且可以在運行時完成選擇。這假定您的接口功能標記爲virtual。示例:

Base* pBase; 
cin >> x; 
if(x == 0) // this is done at runtime, as we don't know x at compile time 
    pBase = new Derived1; 
else 
    pBase = new Derived2; 

pBase->draw(); // draw is a virtual member function 

這對於在運行時調度完成的情況非常有用。簡單地說,向上轉換允許將派生類作爲基類(通過它的通用接口)。

向下鑄造不太有用,應儘量避免使用IMO。一般來說,這是設計不佳的標誌,因爲很少需要將Base對象轉換爲派生對象。這是可以做到(和結果選中)通過dynamic_cast,像

Base* pBase = new Derived; // OK, the dynamic type of pBase is Derived 
Derived* pDerived = dynamic_cast<Derived*>(pBase); 
if(pDerived) // always test 
{ 
    // success 
} 
else 
{ 
    // fail to down-cast 
} 

This link提供了一個非常有用的介紹的主題。

+0

所以代碼行:「pBase = new Derived1;」和「pBase = new Derived2;」實際上代表了上傳?如果是這樣,我們假設x是0,pBase將指向一個「Derived1」類的對象。如果pBase指針是「Derived1 * pBase」,會有什麼區別? – Mihai

+0

@Mhaihai每當你事先不知道派生類型時,它很有用。在這種情況下,您使用指向base的指針來控制派生的層次結構。 – vsoftco

+0

向下鑄造是不好的設計?這是一個瘋狂的要點!由於它會導致未定義的行爲,這在編譯時是未知的,而且在運行時不可預知,所以它正在向上推演那是糟糕的設計。實際上,這是一個向下的例子,它提供了堅實的工作基礎。 – Poriferous