Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is static_cast misused?

I have mixed feelings about static_cast, as it is the safest C++ cast available, but allows both safe and unsafe conversions at the same time, so you have to know the context to say if it is actually safe or might lead to UB (e.g. when casting to a sub-class).

So why isn't there a safer explicit cast? Here is an example, where it could be useful. In COM, they have to return the interface pointer as void** ppv, so "have to" cast explicitely

*ppv = (IInterface*) this;

which was then suggested to be replaced by a safer C++ cast

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

But does it make sense to make even a static_cast here? this is of a class which derives from IInterface, so one could simply write

IInterface* p = this; // implicit conversion to base, safe for sure
*ppv = p;

or use a helper like

template<class T, class U>
T implicit_cast(U p) { return p; }

*ppv = implicit_cast<IInterface*>(this);

So, is it true that static_cast is sometimes misused and can (should?) be replaced by this implicit_cast in some cases, or am I missing something?

EDIT: I know that a cast is required in COM, but it does not have to be static_cast, an implicit cast would be enough.

like image 547
Roman L Avatar asked Feb 10 '11 13:02

Roman L


People also ask

What happens when you perform a static_cast?

The static_cast operator converts a null pointer value to the null pointer value of the destination type. Any expression can be explicitly converted to type void by the static_cast operator. The destination void type can optionally include the const , volatile , or __unaligned attribute.

Can static_cast fail?

static_cast can't throw exception since static_cast is not runtime cast, if some cannot be casted, code will not compiles. But if it compiles and cast is bad - result is undefined.

Why is static_cast better than C style cast?

In short: static_cast<>() gives you a compile time checking ability, C-Style cast doesn't. static_cast<>() is more readable and can be spotted easily anywhere inside a C++ source code, C_Style cast is'nt. Intentions are conveyed much better using C++ casts.

Could you explain to me the difference between static_cast and Dynamic_cast?

static_cast − This is used for the normal/ordinary type conversion. This is also the cast responsible for implicit type coersion and can also be called explicitly. You should use it in cases like converting float to int, char to int, etc. dynamic_cast −This cast is used for handling polymorphism.


1 Answers

In this particular case I believe that it's always known that the casting will be upwards and that therefore static_cast should be perfectly safe.

It does appear that using your implicit_cast would probably be safer, and allows you to explicitly pick which base class you want to implicitly cast to (which is apparently required for COM).

I did a quick test with g++ and implicit_cast does indeed return different addresses for different base classes as expected.

Do note however that in regards to your very first sentence I would argue that dynamic_cast is in fact safer than static_cast since it will return null or throw if the cast can't be completed. In contrast, static_cast will return a valid-looking pointer and let you keep going until your program blows up at some time in the future, unconnected to the original bad cast.

Test program:

#include <iostream>

class B1
{
public:
    virtual ~B1() {}
};

class B2
{
public:
    virtual ~B2() {}
};

class Foo : public B1, public B2
{
};

template<class T, class U>
T implicit_cast(U p) { return p; }

int main()
{
    Foo* f = new Foo;
    void **ppv = new void*;

    *ppv = implicit_cast<B1*>(f);
    std::cout << *ppv << std::endl;;
    *ppv = implicit_cast<B2*>(f);
    std::cout << *ppv << std::endl;;

    return 0;
}
like image 57
Mark B Avatar answered Sep 18 '22 08:09

Mark B