当base从非多态变为多态时,派生类上的static_cast

时间:2010-10-25 08:34:30

标签: c++ casting downcast

我正在审核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以避免任何风险,但代码仍然会在没有任何通知的情况下进行编译。

你怎么做才能意识到这种变化或防止这种情况发生?

由于 AFG

3 个答案:

答案 0 :(得分:3)

你没有包含的背景 - boost有polymorphic_cast作为dynamic_cast<>的包装器,在转换失败时抛出。如果您确定数据属于您要转换的类型,那么static_cast<>就没问题了。无论是否有虚拟成员都没有问题,并且您所包含的代码说它将无法编译将编译并按原样运行。

我猜你在考虑意外投射到另一个派生类的可能性?这是铸造的实用性/危险性,不是吗?您可以添加虚拟析构函数,然后使用dynamic_cast&lt;&gt;,严格来说,RTTI仅适用于具有一个或多个虚函数的类型。

使用static_cast&lt;&gt;编写的代码无论虚拟函数的引入如何,都将继续安全地处理相同的类型...只是如果你开始传递其他类型的代码(即不是CDerived或从中公开衍生的任何东西),那么你将需要dynamic_cast&lt;&gt;或其他一些改变,以防止不兼容的操作。

答案 1 :(得分:1)

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

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

答案 2 :(得分:0)

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

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