2016-12-31 20 views
2

如果您將舊的C風格的類型轉換爲類型A到類型B,而類型A不能轉換爲類型B,那麼C++標準是否定義了特定的行爲?反之亦然?是否定義了運行時錯誤的C風格轉換的行爲?

會有一個已知的可見行爲,可以被認爲是在運行時使用此非法轉換的症狀嗎?

+0

我認爲你應該提供一個例子。例如:你在談論POD類型,類別,原始類型,指針,...? – UnholySheep

+1

好吧,全部都是 – Allahjane

+1

取決於實際的代碼,C風格的轉換可以等同於3種不同C++類型轉換('static_cast','reinterpret_cast'或'const_cast')中的任何一種。這些'static_cast'會拋出編譯時錯誤,而'reinterpret_cast'會(在大多數情況下)導致UB(如果拋出是非法的) – UnholySheep

回答

4

四種C++風格演員中只有一種決定了演員在演出時的合法性,即dynamic_cast

C風格演員陣容對應於其他三個陣容的組合(static_cast,reinterpret_cast,const_cast)。這些演員的有效性是在編譯時確定的,或者如果在編譯時無法確定,那麼演員被認爲是有效的。 C風格演員絕不會像dynamic_cast那樣行事。

因此,在運行時「失敗」的C風格轉換,即打破了有效性假設,導致未定義的行爲。所以:

如果您將舊的C風格的類型轉換爲類型A到類型B,其中類型A不能轉換爲類型B,反之亦然,C++標準是否定義了特定的行爲?

會不會有,可以認爲是使用這種在運行時非法投症狀已知可見的行爲?

+0

感謝這就是我想知道的全部 – Allahjane

+0

[另請參見此處](http://stackoverflow.com/questions/17925124/can-i-cast-a-derived-class-to-a-private-base-class-using -c-style-cast),這個C風格轉換不等同於C++風格轉換的任何組合 –

0

編譯器會趕上他們中的一些,但不是全部。這是一個災難性的鑄件的例子:

#include <iostream> 
#include <string> 

using namespace std; 

class A { 
public: 
     A(std::string s, int x) : m_s(s), m_x(x) {} 

     void print() { cout << "A::print(): str = " << m_s << ", x = " << m_x << endl; } 

private: 
     std::string m_s; 
     int m_x; 
}; 

class B { 
public: 
     B(int x) : m_x(x) {} 
     void print() { m_x++; cout << "B::print(): x = " << m_x << endl; } 

private: 
     int m_x; 

}; 

int main(int argc, char **argv) { 

     A *a = new A("abc", 1); 
     a->print(); 
     B *b = (B*)a; 
     b->print(); 

     a->print(); 

     return 0; 
} 

海合會結果(Ubuntu的5.4.0-6ubuntu1〜16.04.4)5.4.0 20160609:

A::print(): str = abc, x = 1 
B::print(): x = 24828977 
A::print(): str = bc, x = 1 

是的,我們叫B的方法上A的數據,這意味着我們的C風格演員工作爲reinterpret_castreinterpret_cast只需要一個內存區域,並允許你對待是不同的東西。這裏沒有安全帶。

在另一方面,如果你嘗試編譯這樣的事情

A a; 
    B b; 
    a = (A)b; 
    return 0; 

會造成static_cast和編譯時錯誤。所以C風格的轉換結果取決於上下文。

這是NIGHTMARE當處理模板和auto

爲了避免此問題,使用static_cast(用於編譯時檢查)和dynamic_cast(運行時檢查)或reinterpret_cast(用於指針和POD),寫明你的意圖。

+0

實際上你的結果可能只發生在你的機器/編譯器上 - 我得到一個[運行時錯誤](http:// ideone的.com/CsdaXh)。 b:print();'調用*未定義的行爲* – UnholySheep

+0

B :: print()修改由'std :: string'佔據的sizeof(int)'字節。你可能會在那裏觀察到內存腐敗 – ezaquarii

+0

[reinterpret_cast']的文檔(http://en.cppreference.com/w/cpp/language/reinterpret_cast)在此清楚 - 你正在調用UB。也不知道內存損壞是如何影響的,因爲您的結果不能保證,並且不同的編譯器會引發運行時錯誤。 – UnholySheep

相關問題