static_cast被误用了吗?

Rom*_*n L 14 c++ casting static-cast type-safety

我有一种复杂的感觉static_cast,因为它是最安全的C++演员,但同时允许安全和不安全的转换,所以你必须知道上下文,说它是否真的安全或可能导致UB(例如,当铸造时到一个子类).

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

*ppv = (IInterface*) this;
Run Code Online (Sandbox Code Playgroud)

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

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

但即使在static_cast这里也有意义吗?this是一个源自的类IInterface,所以人们可以简单地写

IInterface* p = this; // implicit conversion to base, safe for sure
*ppv = p;
Run Code Online (Sandbox Code Playgroud)

或使用像帮手一样的帮手

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

*ppv = implicit_cast<IInterface*>(this);
Run Code Online (Sandbox Code Playgroud)

那么,是否真的static_cast有时会被滥用,并且implicit_cast在某些情况下可以(应该?)替换它,或者我错过了什么?

编辑:我知道在COM中需要一个强制转换,但它不一定是static_cast,隐式强制转换就足够了.

Mar*_*k B 5

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

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

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

请注意,关于你的第一句话,我认为这dynamic_cast实际上更安全,static_cast因为它将返回null或抛出如果演员无法完成.相反,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;
}
Run Code Online (Sandbox Code Playgroud)

  • @ 7vies:在Visual C++中,它大约有2千个处理器周期,如果你将COM对象转换为错误的类型,编译器将无法捕获你 - 你只会在运行时获得一个空指针. (2认同)