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

时间:2011-02-03 10:17:53

标签: 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;
}

上述实现使用adjusting pointers to account for multiple inheritance的C-cast。它们甚至可以在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风格的演员阵容会导致严重的问题。

还有哪些其他例子?

2 个答案:

答案 0 :(得分:2)

This FAQ item总结了为什么c-casts不好的一切。

任何c-cast都是潜在的炸弹,因为它们通过使编译器静音来隐藏转换警告和错误。

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

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

答案 1 :(得分: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 {};