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 COM 中需要强制转换,但不一定是 static_cast
,隐式强制转换就足够了。
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.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
在这种特殊情况下,我相信总是知道强制转换将向上,因此
static_cast
应该是完全安全的。使用
implicit_cast
似乎确实会更安全,并且允许您显式选择要隐式转换到的基类(这显然是 COM 所必需的)。我用 g++ 做了一个快速测试,
implicit_cast
确实按预期为不同的基类返回了不同的地址。但请注意,关于您的第一句话,我认为
dynamic_cast
实际上比static_cast
更安全,因为如果无法进行强制转换,它将返回 null 或抛出异常。完全的。相反,static_cast
将返回一个看起来有效的指针,并让您继续运行,直到您的程序在未来某个时间崩溃,与原始的错误强制转换无关。测试程序:
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 thanstatic_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: