最近我找到了一个很好的例子来说明为什么 C 风格的转换很糟糕。我们从实现多个 COM 接口(interface)的以下类开始(为简洁起见,我有两个,但在现实生活中可能有十个):
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;
}
上面的实现对 adjusting pointers to account for multiple inheritance 使用了 C-casts .它们甚至作为 static_cast
工作 - this
指针值将被适当调整。
现在我们将相同的 QueryInterface()
实现复制粘贴(或者我应该说重用代码?)到其他一些非常相似的类。
class CMyClassModified : public IInterface1 {
//declarations omitted
};
并保持实现不变。新类不再继承自 IInterface2
但
} else if( iid == __uuidof(IInterface2) ) {
*ppv = (IInterface2*)this;
}
将编译得很好,C 风格的转换将充当 reinterpret_cast
- this
指针值将被原封不动地复制。 调用者将获得一个指向实际未实现 IInterface2
的对象的指针 - 直接导致未定义行为。在一个巨大的数据库中,当有很多(不是我的例子中的两个)接口(interface)时,这样的问题很难被发现。
如果使用 static_cast
则不会发生 - 编译器会在尝试编译时发出错误
*ppv = static_cast<IInterface2*>(this);
在我看来,这是一个足够严酷的例子,说明使用 C 风格的转换会如何导致严重的问题。
还有哪些例子?
最佳答案
This FAQ item总结了为什么 C-cast 不好。
任何 C 风格的转换都可能是炸弹,因为它们通过使编译器静音来隐藏转换警告和错误。
既然你想要一个例子,这里是:
int main()
{
float a = 0.123;
double *b = ( double* ) &a;
*b = 0.123;
}
关于c++ - 有哪些严酷的例子表明 C 风格的转换很糟糕?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4884847/