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,隐式强制转换就足够了.
在这种特殊情况下,我相信人们总是知道铸件是向上的,因此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)