【问题标题】:static_cast on derived classes when base turns from not polymorphic to polymorphic当基类从非多态变为多态时,派生类上的 static_cast
【发布时间】:2010-10-25 08:34:30
【问题描述】:

我正在审查 C++ 强制转换运算符,但我有以下疑问:

对于多态类

  • 我应该使用polymorphic_cast
  • 我不应该使用static_cast,因为向下转换可能会导致未定义的行为。无论如何,代码都会编译这种情况。

现在假设我有以下情况

class CBase{};
class CDerived : public CBase{};

int main( int argc, char** argv ){
    CBase* p = new CDerived();
    //.. do something
    CDerived*pd = static_cast<CDerived*>( p );
}

由于不涉及多态性,我不会使用polymorphic_cast,代码甚至无法编译。

如果在某个时候,有人在继承树中引入了一些 virtual 函数,而我现在意识到了这一点,所以我处于危险之中:我该如何实现它?

我应该转到polymorphic_cast 以避免任何风险,但代码仍会在没有任何通知的情况下编译。

您如何意识到此类变化或防止此类情况发生?

谢谢 自动对焦

【问题讨论】:

  • 代码甚至无法编译 - 你的意思是并且代码可以正常编译
  • CBase 的析构函数不应该是virtual 吗?在这种情况下,您可以使用dynamic_castpolymorphic_cast
  • 在标准 C++ 中没有 polymorphic_cast 这样的东西。你为什么不首先使用CDerived?或者,如果您认为必须使用动态分配,为什么不使用CDerived*?即使您不知道虚拟功能也不会造成任何危险。类名上的所有这些“C”前缀是什么?对我来说,这听起来像是一个严重的口吃案例。干杯,
  • :( 是的..我的意思是 dynamic_cast 不是 boost::polymorphic_cast。最后它是使用 dynamic_cast 实现的,不同之处在于如果 dynamic_cast 返回 0,则抛出 std::bad_cast。今天我需要几个更多的咖啡醒来。
  • P.S.我喜欢将 virtual 添加到析构函数作为每个类的起点并使用 dynamic_cast 的想法/建议

标签: c++ casting downcast


【解决方案1】:

您没有包含的背景 - boost 将 polymorphic_cast 作为 dynamic_cast&lt;&gt; 的包装器,当转换失败时抛出。 static_cast&lt;&gt; 很好,如果您确定数据是您要转换的类型......无论有没有虚拟成员都没有问题,并且您包含的代码说它不会编译将编译并运行就这样就好了。

我猜您正在考虑可能会意外转换为另一个派生类?这就是铸造的效用/危险,不是吗?您可以添加一个虚拟析构函数然后使用 dynamic_cast,因为严格来说 RTTI 仅适用于具有一个或多个虚拟函数的类型。

使用 static_cast 编写的代码将继续安全地处理相同的类型,而不管是否引入了虚函数...只是如果您开始将该代码传递给其他类型(即不是 CDerived 或任何从其公开派生的),那么您将需要 dynamic_cast 或其他一些更改来防止不兼容的操作。

【讨论】:

  • 嗨托尼!我喜欢这个主意。默认情况下将 virtual 放入析构函数将防止我的问题,同时我将完全没有泄漏。非常感谢!
  • @abruzzo-forte-e-gentile:我知道很多人选择这样做(默认情况下使用虚拟析构函数),但请注意这样做有一些成本。它很小,但我想说,如果您希望类被多态使用(即,至少还有一种其他方法也被声明为虚拟的),那么您应该只求助于将析构函数设为虚拟。
【解决方案2】:

当您处理指针 p(类型为 CBase*)时,指向的对象将被视为 CBase,但所有虚函数都会做正确的事情。指针 pd 将相同的对象视为 CDerived。以这种方式向上转换是危险的,因为如果对象不是从向上转换的类型派生的,则向上转换对象的任何额外成员数据都将丢失(这意味着您将在一些其他数据中四处寻找),并且虚函数查找将是一切都搞砸了。这与向下转换(如您已标记此问题)相反,您可能会得到slicing

为避免这种情况,您需要改变您的编程风格。将同一对象视为两种不同类型是一种可疑的做法。 C++ 可以非常擅长强制执行类型安全,但如果你真的想要,或者只是不知道更好,它会让你摆脱讨厌的事情。如果你想根据对象类型做不同的事情,并且不能通过虚函数(例如通过double dispatch)来做,你应该更深入地研究RTTI(look here,或者看看一些很好的例子@ 987654324@).

【讨论】:

    【解决方案3】:

    polymorphic_cast 未在 C++ 中定义。你在考虑 dynamic_cast 吗?

    无论如何,你无法阻止它。

    【讨论】:

    • boostpolymorphic_cast。我猜 OP 正在使用它。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2019-04-17
    • 1970-01-01
    • 2016-07-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多