2015-12-03 20 views
-1

我試着動態地將一個根對象引用強制轉換爲子類對象引用。我認爲這是非常正常的邏輯。但意外的是,子類複製構造函數已被調用。在macosx平臺相同性測試用例中執行正確。 爲什麼!我想知道理由。可能是視覺工作室2015的一個bug。爲什麼dynamic_case引用會生成copy-construct函數調用

class IObject 
{ 
public: 
    IObject() 
    {} 
    IObject(const IObject &ins) 
    { 

    } 
    virtual ~IObject() 
    {} 
}; 

class CObject : public IObject 
{ 
public: 
    CObject() 
    {} 
    CObject(const CObject &ins) 
    { 
     std::cout << "CObject copy constract function has be call" << std::endl; 
    } 
    virtual ~CObject() 
    {} 
}; 

int main(int argc, _TCHAR* argv[]) 
{ 

    CObject *pCObject= new CObject(); 

    IObject *pIObject = pCObject; 

    CObject &objectRef = dynamic_cast<CObject*>(pIObject) == NULL ? throw std::exception() : dynamic_cast<CObject&>(*pIObject); 

    return 0; 
} 

以下是我的測試環境和結果。

測試環境:visual studio 2015,windows 10 64bit 程序語言:C++ 測試結果:CObject copy constract函數有調用。

測試環境:Xcode 7,Macosx 程序語言:C++ 測試結果:CObject copy constract函數不被調用。

+0

你知道是什麼行拷貝構造函數被調用呢? –

+0

@Nicol:我認爲三元組正在評估一個右值,通過創建一個臨時值(MSVC行爲,違反標準)來引用該值。 –

+0

@ BenVoigt:這是一個長期以來的事情,VS2015警告說至少在合理的警告水平上)。我擔心的是,如果表達式評估爲右值,那麼編譯器會失敗並報錯。這是標準的行爲,對吧?因此,這裏正在發生其他事情。另外,throw表達式的結果究竟是什麼?因爲這種類型應該是三元表達式的結果,對嗎?這個代碼是不是合法的,這真的不清楚。 –

回答

0

你知道,這個簡單的線條

CObject &objectRef = dynamic_cast<CObject&>(*pIObject); 

已經做了運行時檢查你正在編寫,並拋出一個bad_cast_exception如果失敗。

不要重新發明輪子。

你的代碼是符合標準的,看來MSVC不正確地從部分5.16實施此規則:

如果第二個或第三個操作數的類型爲void,以下的人不得持有:

  • 第二或第三操作數(但不是兩者)是一個(可能是括號內)拋出表達式(5.17);結果是另一個的類型和值類別。如果操作數是一個位域,則條件表達式是一個位域(如果 )。
  • 第二個和第三個操作數都有void型;結果是void類型並且是一個prvalue。 [注意:這包括兩個操作數都是throw-expressions的情況。 - 注完]

由於MSVC不保留其他操作的價值範疇,它被複制到一個臨時的。

另一個解決方法是

if (dynamic_cast<CObject*>(pIObject) == NULL) throw std::exception(); 
CObject &objectRef = dynamic_cast<CObject&>(*pIObject); 
+0

我同意你的觀點。我認爲微軟的C++編譯器存在bug。 –

相關問題