2011-02-03 42 views
5

最近我發現了一個很好的例子,說明爲什麼C風格演員是壞的。我們先從下面的類實現多個COM接口(我有兩個爲簡潔,但在實際生活中有十):有什麼嚴酷的例子顯示C風格的演員是壞的?

class CMyClassInitial : public IInterface1, public IInterface2 { 
    //declarations omitted 
}; 

HRESULT CMyClassInitial::QueryInterface(REFIID iid, void** ppv) 
{ 
    if(ppv == 0) { 
     return E_POINTER; 
    } 
    *ppv = 0; 
    if(iid == __uuidof(IUnknown) || iid == __uuidof(IInterface1)) { 
     *ppv = (IInterface1*)this; 
    } else if(iid == __uuidof(IInterface2)) { 
     *ppv = (IInterface2*)this; 
    } else { 
     return E_NOINTERFACE; 
    } 
    AddRef(); 
    return S_OK; 
} 

以上實現使用C-類型轉換爲adjusting pointers to account for multiple inheritance。他們甚至可以按照static_cast s - this的指針值進行適當的調整。

現在我們複製粘貼(或者我應該說重用代碼的?)相同的QueryInterface()執行到一些其他非常相似的類。

class CMyClassModified : public IInterface1 { 
    //declarations omitted 
}; 

並保持實施相同。新的類不從IInterface2了繼承,但

} else if(iid == __uuidof(IInterface2)) { 
*ppv = (IInterface2*)this; 
} 

會編得很好,C樣式轉換將作爲reinterpret_cast - this指針值將被原樣複製。 調用者將獲得一個指向實際上沒有實現的對象的指針IInterface2 - 未定義行爲的直接方式。這樣的問題很難在龐大的數據庫中發現,並且當有很多(不是我的例子中的兩個)接口時。

如果static_cast使用,不會發生 - 編譯器會發出錯誤試圖編譯

*ppv = static_cast<IInterface2*>(this); 

IMO這是如何使用C-風格轉換可能會導致嚴重的問題的惡劣足夠的例子。

還有其他的例子嗎?

+0

一個偉大的疑難雜症,但我不能完全肯定這是適合左右。這似乎很討論。充其量,這是一個社區維基。 – tenpn 2011-02-03 10:25:16

+0

@tenpn:我沒有看到這裏可以討論什麼 - 只是在C++中用自己的腳步拍攝的一個例子。 – sharptooth 2011-02-03 10:28:46

回答

2

This FAQ item總結了爲什麼c-casts不好。

任何c-cast都是潛在的炸彈,因爲它們通過沉默編譯器隱藏了轉換警告和錯誤。

既然你想要一個例子,那就是:

int main() 
{ 
    float a = 0.123; 
    double *b = (double*) &a; 
    *b = 0.123; 
} 
1

一個很簡單的例子:

class ClassB;//only forward declaration, no real declaration included 

Class A * a; 
Class B * b; 
a = (ClassA *)b; 

演員永遠是默默的成功,如果有隻ClassB的向前聲明。它不關心ClassB是否來自ClassA。 而這也將是錯誤的,當ClassB的不僅是從ClassA的派生:

class ClassB:public SomeOtherClass, public ClassA {};