有哪些苛刻的例子显示C风格的演员阵容很糟糕?

sha*_*oth 5 c++ casting

最近我发现了一个很好的例子,说明为什么C风格的演员阵容很糟糕.我们从下面的类开始实现多个COM接口(为了简洁我有两个,但在现实生活中可能有十个):

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;
}
Run Code Online (Sandbox Code Playgroud)

上面的实现使用C-casts来调整指针以考虑多重继承.它们甚至可以作为static_casts - this指针值进行适当调整.

现在我们复制粘贴(或者我应该说重用代码?)相同的QueryInterface()实现到其他一些非常相似的类.

class CMyClassModified : public IInterface1 {
    //declarations omitted
};
Run Code Online (Sandbox Code Playgroud)

并使实现保持不变.新类不再继承IInterface2

} else if( iid == __uuidof(IInterface2) ) {
*ppv = (IInterface2*)this;
}
Run Code Online (Sandbox Code Playgroud)

将编译得很好并且C风格的强制转换将充当reinterpret_cast- this指针值将被复制不变.调用者将获得指向实际上未实现的对象的指针IInterface2 - 直接指向未定义的行为.这样的问题很难在庞大的数据库中找到,并且当有很多(在我的例子中不是两个)接口时.

如果static_cast使用了不会发生的事情 - 编译器会在尝试编译时发出错误

*ppv = static_cast<IInterface2*>(this);
Run Code Online (Sandbox Code Playgroud)

对于如何使用C风格的演员表而言,IMO是一个非常严厉的例子,可能会导致严重的问题.

还有哪些其他例子?

BЈо*_*вић 2

此常见问题解答项目总结了 C 型铸造不好的原因。

任何 C 风格的强制转换都可能是炸弹,因为它们通过使编译器静音来隐藏转换警告和错误。

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

int main()
{
    float a = 0.123;
    double *b = ( double* ) &a;
    *b = 0.123;
}
Run Code Online (Sandbox Code Playgroud)

  • 很好的常见问题解答项目,但它是关于一般的演员阵容,而不是专门针对 C 演员阵容。 (2认同)