【问题标题】:static_cast vs dynamic_caststatic_cast 与 dynamic_cast
【发布时间】:2011-06-06 14:12:45
【问题描述】:

假设我得到了一个充满继承的 C++ 库。当我知道函数实际上指向Derived 对象并且Derived 继承Base 时,我在函数中得到了Base*。但我不知道它是哪种继承(公共/受保护/私有)。我也不知道层次结构中有没有虚函数。

鉴于这种情况,不查看BaseDerived 的源代码/文档,我应该使用哪个演员表?还是我应该先查阅代码/文档以确保多态性?

背景

我正在 Qt 4.7 中编写 QMainWindowchangeEvent 函数。 changeEvent 函数采用 QEvent*,我可以通过知道 QEvent::type() 将其转换为其他类型。我想知道我应该使用static_cast 还是dynamic_cast

谢谢。

【问题讨论】:

  • 如果你使用的任何库使用protected继承,是时候寻找更好的编写库了。
  • 这个问题可能会有所帮助:stackoverflow.com/questions/28002/…
  • @Zac:希望我能对 cme​​ts 投反对票。如果您不知道该库的作用,您如何判断受保护的继承是否是适合这项工作的工具?
  • @DeadMG:protected 继承绝对没有用。 private 继承有其用途(尽管应该谨慎使用),但 protected 完全没用。
  • @DeadMG:我倾向于同意 Zac,protected 确实是一个奇怪的可访问性级别 - 对某些功能(主要是构造函数/析构函数)有些有用,它通常对属性,我无法理解哪种奇怪的继承层次结构实际上会需要受保护的继承。

标签: c++ casting


【解决方案1】:

使用static_cast。如果您知道您的Base* 指向Derived,则使用static_castdynamic_cast 在它可能指向派生对象时很有用。

【讨论】:

  • 你现在可能知道了。但是他正在使用一个库,我确信该库没有提供他们不会更改实现细节的保证。接口是 Base*,因此您可以假设是 ALL。因此,您必须使用 dynamic_cast,以便检查您的假设是否成立。
  • @Martin:这是他的问题,不是我的。如果他知道它确实指向派生,那么该知识的根源超出了我可能回答的范围。
  • 问题是他不知道。他的知识仅限于这一特定实例的时空坐标。因此,我们需要强调 OP 在他知道他的假设中是错误的。他现在知道,但知识不能转移到未来。因此,因为他是错误的 static_cast 是错误的答案(如果 OP 是正确的(但他不是),这是正确的答案)。唯一可以假设接口是 Derived 的情况是它返回 Derived* 否则它可能会返回从 Base* 派生的任何东西(这就是我们在代码中使用接口的原因)。
  • 只是为了记录,我已经使用了这个,你也可以使用 typeid() 检查来检查类型。
【解决方案2】:

如有疑问,您应该首选dynamic_cast。它可能会慢一些,但您可能不会注意到其中的差异。

如果你需要速度,使用下面的sn-p:

template <typename Derived, typename Base>
Derived safe_static_cast(Base b)
{
  assert((void*)dynamic_cast<Derived>(b) && "safe_static_cast failed!");
  return static_cast<Derived>(b);
}

或类似的东西。

这个想法是,在调试版本中,它会检查它是否确实是您认为的那样,然后发布版本......好吧,一切都已经过测试了,不是吗?

【讨论】:

  • 你不需要(void*)演员
  • @Gene: 确实很难看 :) 我试图避免参考案例的重载。
【解决方案3】:

来自 MSDN -

一般来说,当您想将数字数据类型(例如枚举转换为整数或整数转换为浮点数)时,您会使用 static_cast,并且您确定转换中涉及的数据类型。 static_cast 转换不如 dynamic_cast 转换安全,因为 static_cast 不做运行时类型检查,而 dynamic_cast 做。指向不明确指针的 dynamic_cast 会失败,而 static_cast 会返回,就好像没有出错一样;这可能很危险。虽然 dynamic_cast 转换更安全,但 dynamic_cast 只对指针或引用起作用,运行时类型检查是一种开销。

欲了解更多信息,请查看link

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2010-11-18
    • 2014-05-29
    • 1970-01-01
    • 2010-09-06
    • 2011-01-16
    • 1970-01-01
    相关资源
    最近更新 更多