是否有任何与dynamic_cast错误处理相关的良好实践(除非您不必使用它)?我想知道我应该如何处理NULL和它可以抛出的bad_cast。 我应该检查两者吗?如果我捕获bad_cast或检测到NULL,我可能无法恢复... 现在,我正在使用assert来检查dynamic_cast是否返回NULL值。你会在代码审查中接受这个解决方案吗?
答案 0 :(得分:24)
如果dynamic_cast
应该成功,那么最好使用boost::polymorphic_downcast
,这有点像这样:
assert(dynamic_cast<T*>(o) == static_cast<T*>(o));
return static_cast<T*>(o);
这样,您将检测调试版本中的错误,同时避免发布版本中的运行时开销。
如果您怀疑演员可能失败并想要检测它,请使用dynamic_cast
并转换为引用类型。如果出现错误,此演员表将抛出bad_cast
,并将取消您的程序。 (如果,正如你所说,无论如何你都不会恢复,这是好事。)
T& t = dynamic_cast<T&>(o);
t.func(); //< Use t here, no extra check required
仅当0指针在上下文中有意义时才将dynamic_cast
用于指针类型。您可能希望在if
中使用它,如下所示:
if (T* t = dynamic_cast<T*>(o)) {
t->func(); //< Use t here, it is valid
}
// consider having an else-clause
使用最后一个选项,如果dynamic_cast
返回0,则需要确保执行路径有意义。
直接回答你的问题:我更喜欢我在代码中明确assert
的两个首选方案之一:)
答案 1 :(得分:23)
仅在投射引用
时抛出bad_castdynamic_cast< Derived & >(baseclass)
在转换指针时返回NULL
dynamic_cast< Derived * >(&baseclass)
所以从来没有必要同时检查两者。
断言是可以接受的,但这在很大程度上取决于上下文,那么,对于几乎每个断言都是如此......
答案 2 :(得分:2)
是和否。
boost::polymorphic_downcast<>
肯定是在调试阶段处理dynamic_cast<>
错误的好选择。但值得一提的是,只有在可以预测在编译时传递的多态类型时才应使用polymorphic_downcast<>
,否则应使用dynamic_cast<>
代替它。
然而是一系列:
if (T1* t1 = dynamic_cast<T1*>(o))
{ }
if (T2* t2 = dynamic_cast<T2*>(o))
{ }
if (T3* t3 = dynamic_cast<T3*>(o))
{ }
表示一个非常糟糕的设计,应该由多态和虚函数来解决。
答案 3 :(得分:1)
这取决于......; - )
如果我真的希望dynamic_cast
给我一些可用的东西,例如,如果我和其他人没有将多态类型添加到指向基类的指针的容器中,那么我将使用引用转换和让std::bad_cast
杀死我的应用程序 - 真的没有别的事可做。
但是,如果我查询某个接口所暴露的某些功能的多态类型,它不一定要实现,那么我会使用指针转换,然后NULL就不会出错(当然,除非我期望真的的能力在那里 - 但是那时我已经去了参考演员......)
答案 4 :(得分:0)
我同意'它依赖'的答案,并且还添加了“优雅降级”:仅仅因为演员在某处失败并不足以让应用程序失败(并且用户失去他/她的工作等等) )。我建议结合断言和防御性编程:
ptr = dynamic_cast<MyClass>(obj);
ASSERT(ptr);
if(ptr)
{
// do stuff
}