2014-12-23 16 views
4

看我的代碼,我可以投GoodMan指針指向一個Man指針,並使用兩個步驟傳遞給AddMan函數。但是當我使用一步來做到這一點時,它不起作用。相反,它需要將Man指針引用明確指向不僅指向Man指針。這背後的原因是什麼?指示燈通過放置傳遞

class Man{ 
    }; 

    class GoodMan: public Man 
    { 
    }; 

    void AddMan(Man*& man){}; 

    int main() 
    { 
     GoodMan* good_man = new GoodMan() ; 

     //This works 
     Man* pMan2 = (Man*)good_man;  
     AddMan(pMan2); 

     //So I think this should work, But doesn't work 
     AddMan((Man*)good_man); 

     //But this works 
     AddMan((Man*&)good_man); 

     return 0; 
    } 
+0

MingW TDM GCC明確指出編譯錯誤中的問題,main.cpp:26:26:錯誤:從類型爲'Man *'的右值非類型'Man *&'的非const引用的無效初始化 AddMan (曼*)good_man); – user1

+0

爲什麼你需要通過引用傳遞指針?按價值傳遞! –

+0

@vincent。這只是一個示例來展示這種情況。 –

回答

3

AddMan((Man*&)good_man);導致未定義的行爲。這是將GoodMan *別名爲Man *,這是不允許的。這是一個reinterpret_cast

雖然GoodManMan衍生GoodMan *不是從Man *「衍生」,他們是不兼容的類型。

例子:

AddMan(static_cast<Man*&>(good_man)); // error: invalid static_cast 

AddMan(reinterpret_cast<Man*&>(good_man)); // no error, but runtime UB 

爲了幫助 「嗅出」 這個問題,想想void AddMan(Man*& man);功能。它接受對Man *的引用。它必須用一個實際上是Man *的變量來調用。該參考必須具體綁定到Man *。在您的原始代碼中,參考具有哪些約束? good_man不是Man *

+0

您將我拖到了完全不同的地步。所以,如果我暫停C++標準,我不應該使用'AddMan((Man *&)good_man)'方法? –

+1

而且有些相關:Man * pMan2 =(Man *)good_man;'是不必要的,不應該用於防止意外隱藏無效轉換。 –

+3

沒錯。事實上,從來沒有使用C風格的演員將幫助你避免陷阱。無效的'static_cast'通常會給出錯誤(但並非總是)。 –

9

C++不允許結合右值(bacically臨時量)這樣小號(Man*)good_man到非const左值的引用,如Man*&。在你的代碼中,pMan2是一個左值,所以它可以綁定到非const參考參數AddMan。但(Man*)good_man是一個右值。這是錯誤的原因。

如果您更改AddMan的簽名以獲取const左值引用,您的代碼將被編譯。

void AddMan(Man* const& man){}; 

當然,這不允許您更改作爲參數傳遞的指針。另一方面,就編譯代碼而言,將您的解決方案轉換爲左值引用「工作」。但是你必須問自己,修改AddMan函數內部的指針意味着什麼。

AddMan((Man*&)good_man); // "works" by pretending everything is OK. It isn't. 
+0

所以你的意思是(Man *&)good_man'不是一個右值?你能否請進一步解釋一下'(Man *&)good_man'在那裏如何工作? –

+2

@NayanaAdassuriya'(Man *&)good_man'是一個指向'Man'的指針的左值。這是該功能所期望的。當你指的是一個'GoodMan *'時,你正在愚弄編譯器,認爲它正在引用一個'Man *'。這並不真正「有效」。它只是編譯。 – juanchopanza

0

(Man*)good_manrvalue,因此不能結合的Man*的參考。另一方面,(Man*&)good_man已經被鑄造成兼容型並且工作正常。請注意,如果您將AddMan的簽名更改爲採用const引用,則所有示例都可以正常工作。

1

這是因爲(Man*)good_manr值(即暫時的)而(Man*&)good_manpMan2-1-值

當綁定的引用:

  1. -1-值參考Man& = -1-值
  2. r值參考Man&& = r值
  3. const的升 - 價值參考const Man& =任何類型的參考
  4. const的r值參考const Man&& = const和non-const的r值

你有作爲函數參數什麼是1-值引用,因此可以僅結合l值

謝謝您的閱讀。

+0

哦,謝謝你。 – Nard

+0

有一個棘手的情況5.如果'T'是一個依賴模板參數,那麼'T &&'可以綁定到非const rvalues和左值。 –

+0

@MattMcNabb你是指引用崩潰? – Nard