2015-12-17 38 views
3

準確地說,爲什麼B b = (B&) a編譯和工作,而B b = (B) a不在下面的程序?在C++中,爲什麼要引用派生類型的引用?

#include <iostream> 
using namespace std; 

class A {public: void f(){ cout<<"A"<<endl;} }; 

class B : public A { public: void f(){cout<<"B"<<endl;} }; 

void g(A a){ B b = (B&) a; b.f(); } 

int main() { 
    B b; g(b); 
    return 0; 
} 

是否有一些關於鑄造派生類型的參考,我在這裏失蹤?如果我只投射到B,會給編譯時錯誤,即構造函數B(A a)不存在。

+0

你這是什麼MEAM的 「爲什麼」?你是否需要標準中的引用來指定這種行爲?或者一個深刻的哲學理由,爲什麼這樣做會是一個壞主意? –

+0

顯然是第一個。我不知道爲什麼標準允許轉換爲派生類型引用,但不能派生類型實例。如果引用是通過標準解釋爲指針,那將是有意義的。 –

+0

當你需要的是''\ n''時,不要使用'std :: endl'。 –

回答

1

因爲從AB的隱式轉換不存在,您也沒有定義明確的轉換。

另一方面,引用強制轉換是有效的,因爲它允許繼承類型。更確切地說,您可以在同一繼承層次結構中的不同類之間建立兩種方式。指針也一樣。如果你想要進一步研究一些指針,相關概念被稱爲多態性

待辦事項,但是,它纔有意義的對象B強制轉換爲B。 E.摹:

B b; 
A& aRef = B; // equivalent of A& ref = (A&)B; 
B& bRef = (B&)aRef; 

做過什麼,在運行時只要您嘗試訪問某些數據或B方法不存在A失敗。因爲你的實際對象是A,而不是B

上傳(從後代到上升)總是安全的,因爲繼承基類的類的任何對象都是是有效的基礎對象。然而,向下轉換對於我上面解釋的確切原因是危險的,並且決不應該使用C風格演員來完成。相反,使用dynamic_cast

B b; 
A& aRef = B; 
B& bRef = dynamic_cast<B&>(aRef); 

dynamic_cast使用RTTI(運行時類型信息)來驗證操作,如果轉換無效將拋出一個異常std::bad_cast。這不像dynamic_cast ing指針,在這種情況下,演員會返回nullptr而不是拋出異常。

+0

我已經確保它在我的函數調用中只有派生類型的實例被傳遞給以基類型爲參數的函數。所以運行時失敗永遠不會發生。 另外,你是否試圖說類型轉換爲派生類型的引用工作,因爲在場景後面,C++將引用解釋爲指針?因爲我知道在這裏使用指針來代替引用的事實會起作用。我只是不確定這是一個C++標準規範來將引用解釋爲指針。 –

+0

「只有派生類型的實例被傳遞給以基類型爲參數的函數」。那麼爲什麼它將基類型作爲參數,如果它總是得到派生類型呢?編譯器隱藏類型有什麼意義? –

+0

該標準沒有說*後臺引用是指針 - 但這就是每個編譯器實現它們的方式 –

-1

A級有私人/公共成員。 B類來源於A類,可能已增加更多私人/公共成員。

B類「是一個」類A的衍生物但是A類「不是」 B類的衍生物(IE:可以向下轉換A-> B而不是向上轉型BA)

原因是,儘管B是一種A,但A不是B的一種,所以B的方法/成員不會出現(即使方法在源代碼中具有相同的名稱,也不會因爲名稱而編譯相同的方法被編譯器遮蔽)。

+3

這似乎沒有回答這個問題。 – juanchopanza

+0

同意。另外,雖然我明白你想說什麼,但沒有人會問這個問題。 –

1

B b = (B) a將不起作用,因爲沒有定義轉換(構造函數或轉換運算符)。 B b = (B&) a工作原因是它將a轉換爲引用B(downcast by static_cast),然後調用B的構造函數。但是在這種情況下,a不是B的實際對象,所以這是未定義的行爲。 請參閱[expr.static。用C投] ++標準

如果type「CV1 B」的對象實際上是類型d的對象的一個​​子對象,其結果是指類型D的包圍 對象否則,該行爲是未定義。

和[expr.cast]在C++標準或http://en.cppreference.com/w/cpp/language/explicit_casthttp://en.cppreference.com/w/cpp/language/cast_operator

+2

這個措辭令人困惑; C風格演員正在執行'reinterpret_cast',因爲它允許任何左值被轉換爲任何類型*的引用。這聽起來像是暗示C風格演員正在執行'static_cast'。 –

+1

在[expr.cast]部分和http://en.cppreference.com/w/cpp/language/explicit_cast中,C風格強制轉換將按照以下順序執行:const_cast,static_cast,static_cast(後面加上'const_cast','reinterpret_cast','reinterpret_cast'後面跟着'const_cast' – Danh

+0

@CollinDauphinee在這種情況下,它應該執行'static_cast '。 – juanchopanza

相關問題