我正在审核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
答案 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吗?
无论如何,你无法阻止它。