dynamic_cast
s较慢,但它们比static_cast
更安全(当然,当与对象层次结构一起使用时)。我的问题是,在我的调试代码中确保所有(动态)强制转换都是正确的之后,我有理由不将它们更改为static_cast
吗?
我计划使用以下构造执行此操作。 (顺便说一下,你能想到一个比assert_cast
更好的名字吗?也许debug_cast
?)
#if defined(NDEBUG)
template<typename T, typename U>
T assert_cast(U other) {
return static_cast<T>(other);
}
#else
template<typename T, typename U>
T assert_cast(U other) {
return dynamic_cast<T>(other);
}
#endif
修改:Boost已经有了这方面的内容:polymorphic_downcast
。感谢PlasmaHH指出这一点。
答案 0 :(得分:4)
没有! dynamic_cast
不仅仅是投射。它可以检查对象的运行时类型。但它也可以遍历编译器未知的层次结构,但仅在运行时中已知。 static_cast
无法做到这一点。
例如:
class A1
{
virtual ~A1() {}
};
class A2
{
virtual ~A2() {}
};
class B : public A1, public A2
{ };
A1 *a1 = new B;
A2 *a2 = dynamic_cast<A2*>(a1); //no static_cast!
A1 *x = ...;
if (B *b = dynamic_cast<B*>(x)) //no static_cast!
/*...*/;
答案 1 :(得分:2)
您应断言dynamic_cast
成功:
template<typename T, typename U>
T *assert_cast(U *other) {
T *t = dynamic_cast<T>(other);
assert(t);
return t;
}
在您确定它们是等效的情况下,用dynamic_cast
替换static_cast
与删除您确定始终为非null的指针的空检查相同。出于性能原因,您可以这样做。
答案 2 :(得分:2)
只要您使用运行时因子/变量/输入的每种可能组合进行测试,请确保。正如评论中所提到的,这类似于删除断言。
在语言中没有任何东西可以使这种本身不安全,因为必须保证你的演员阵容永远是正确的。但它确实感觉不安全,因为你可能永远不会做出这样的保证。
Konstantin已经证明,在处理多重继承时,这种技术只适用于继承树上/下单步 1 。
struct A1 { virtual ~A1() {} };
struct A2 { virtual ~A2() {} };
struct A3 { virtual ~A3() {} };
struct B : A1, A2 {};
struct C : A1, A3, A2 {};
int main() {
A1* a1 = (rand() < RAND_MAX / 2 ? (A1*)new B : (A1*)new C);
A2* p1 = dynamic_cast<A2*>(a1);
// ^ succeeds, but is a cross-cast
// A2* p2 = static_cast<A2*>(a1);
// ^ ill-formed
A2* p3 = static_cast<A2*>(static_cast<B*>(a1));
// ^ must chain, instead.
// but p3 is invalid because we never
// checked that `dynamic_cast<B*>(a1)` is valid.. and it's not
// Instead, let's expand the `dynamic_cast`s into a chain, too:
A2* p3 = dynamic_cast<B*>(a1);
A2* p4 = dynamic_cast<A2>*(a1);
// ^ p3 fails, so we know that we cannot use `static_cast` here
}
因此,您可以将dynamic_cast
替换为static_cast
的iff:
dynamic_cast
仅执行单个步骤; dynamic_cast
都会成功。1 实际上这有点简化,例如,向下转换将适用于任意数量的步骤。但这是一个很好的经验法则。
答案 3 :(得分:1)
我想这取决于项目。如果它是核电站管理软件,那么我宁愿安全,如果是3D游戏我更喜欢性能。您永远不能确定生产代码中的所有dynamic_cast
都是正确的。如果性能比安全性更重要,则删除。
答案 4 :(得分:1)
在我的调试代码中确保所有(动态)强制转换后 对,我有什么理由不改变它们 static_casts?
恕我直言,如果你100%确定所有 dynamic_cast<>
都是正确的,那么没有理由就没有将它们更改为static_cast<>
。您可以更改。