2011-02-03 62 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 {};