在生产代码中是否可以安全地删除dynamic_casts?

时间:2011-09-09 09:33:31

标签: c++ performance casting dynamic-cast

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指出这一点。

5 个答案:

答案 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<> 。您可以更改