What harsh examples are there showing C-style casts are bad?

▼魔方 西西 提交于 2019-12-13 11:49:34

问题


Recently I found a great example of why C-style casts are bad. We start with a following class implementing multiple COM interfaces (I have two for brevity, but there can be ten in real life):

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;
}

The above implementation uses C-casts for adjusting pointers to account for multiple inheritance. They even work as static_casts - this pointer value will be properly adjusted.

Now we copy-paste (or should I say reuse code of?) the same QueryInterface() implementation to some other very similar class.

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

and leave the implementation the same. The new class doesn't inherit from IInterface2 anymore but

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

will compile just fine and C-style cast will act as reinterpret_cast - this pointer value will be copied unchanged. The caller will obtain a pointer to an object that doesn't actually implement IInterface2 - straight way to undefined behavior. Such problems can be hard to spot in a huge database and when there're many (not two as in my example) interfaces.

If static_cast was used that would not have happened - the compiler would emit an error trying to compile

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

IMO that's a harsh enough example of how using C-style casts can cause serious problems.

What other examples are there?


回答1:


This FAQ item sums everything about why c-casts are bad.

Any c-cast is potentiality a bomb, since they are hiding conversion warnings and errors by silencing the compiler.

Since you wanted an example, here it is :

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



回答2:


A very simple example:

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

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

The cast will always be silently successful if there's only forward declaration of ClassB. It doesn't care if ClassB is derived from ClassA. And it will also be wrong when ClassB is not only derived from ClassA:

class ClassB:public SomeOtherClass, public ClassA {};


来源:https://stackoverflow.com/questions/4884847/what-harsh-examples-are-there-showing-c-style-casts-are-bad

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!