static_cast被误用了吗?

时间:2011-02-10 13:37:12

标签: c++ casting type-safety static-cast

我对static_cast感到复杂,因为它是最安全的C ++演员,但允许同时进行安全和不安全的转换,因此您必须知道上下文,以确定它是否真的安全或可能会导致UB(例如,当投射到子类时)。

那么为什么没有更安全的明确演员呢?这是一个例子,它可能是有用的。在COM中,他们必须将接口指针返回为void** ppv,因此“必须”明确地转换

*ppv = (IInterface*) this;

然后建议用更安全的C ++演员代替

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

但是在这里做一个static_cast是否有意义? this是一个派生自IInterface的类,因此可以简单地编写

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

或使用像

这样的帮手
template<class T, class U>
T implicit_cast(U p) { return p; }

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

那么,static_cast是否有时被滥用并且在某些情况下可以(应该?)被这个implicit_cast取代,或者我错过了什么?

编辑:我知道a cast is required in COM,但它不一定是static_cast,隐式演员就足够了。

1 个答案:

答案 0 :(得分:5)

在这种特殊情况下,我相信人们总是知道铸造是向上的,因此static_cast应该是完全安全的。

看来使用implicit_cast可能会更安全,并且允许您明确选择要隐式转换到哪个基类(这显然是COM所必需的)。

我使用g ++进行了快速测试,而implicit_cast确实为预期的不同基类返回了不同的地址。

请注意,关于你的第一句话,我认为dynamic_cast实际上比static_cast更安全,因为如果无法完成演员,它将返回null或throw。相比之下,static_cast将返回一个有效的指针,让你继续前进,直到你的程序在未来的某个时间爆炸,与原始的糟糕演员无关。

测试程序:

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