【问题标题】:Is static_cast misused?static_cast 被滥用了吗?
【发布时间】:2011-02-10 13:37:11
【问题描述】:

我对@9​​87654323@ 有复杂的感觉,因为它是可用的最安全的 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,隐式转换就足够了。

【问题讨论】:

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


【解决方案1】:

在这种特殊情况下,我相信大家都知道投射会向上,因此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;
}

【讨论】:

  • 确实,dynamic_cast 会比 static_cast 更安全,但我没有提到它,因为我从未见过它实际使用过(我听说过性能下降但不知道有多大它是)。
  • @7vies:在 Visual C++ 中,它大约有 2000 个处理器周期,如果你将 COM 对象转换为错误的类型,编译器将无法捕捉到你——你只会在运行时得到一个空指针。
  • @sharptooth:是的,dynamic_cast 绝对不是 COM 上下文中的最佳选择。我什至不确定在哪种情况下它可能是一个不错的选择 - 在大多数情况下,它可以被运行时或编译时多态性所取代,这会同时更安全和更快。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-10-18
  • 1970-01-01
  • 2011-11-21
  • 2011-05-07
  • 2011-04-07
  • 2018-04-26
相关资源
最近更新 更多