静态投与投dymamic遍历继承层次(Static cast vs. dymamic cast fo

2019-08-03 22:16发布

我看到了基于C一本书++提的是,使用静态浇铸导航继承层次结构比使用动态转换效率更高。

例:

#include <iostream>
#include <typeinfo>

using namespace std;

class Shape { public: virtual ~Shape() {}; };
class Circle : public Shape {};
class Square : public Shape {};
class Other {};

int main() {
    Circle c;

    Shape* s = &c; // Upcast: normal and OK

    // More explicit but unnecessary:
    s = static_cast<Shape*>(&c);
    // (Since upcasting is such a safe and common
    // operation, the cast becomes cluttering)

    Circle* cp = 0;
    Square* sp = 0;

    // Static Navigation of class hierarchies
    // requires extra type information:
    if(typeid(s) == typeid(cp)) // C++ RTTI
        cp = static_cast<Circle*>(s);
    if(typeid(s) == typeid(sp))
        sp = static_cast<Square*>(s);
    if(cp != 0)
        cout << "It's a circle!" << endl;
    if(sp != 0)
        cout << "It's a square!" << endl;

    // Static navigation is ONLY an efficiency hack;
    // dynamic_cast is always safer. However:
    // Other* op = static_cast<Other*>(s);
    // Conveniently gives an error message, while
    Other* op2 = (Other*)s;
    // does not
} ///:~

然而,无论是动态转换和静态浇铸(如上实现)需要启用RTTI这样的导航工作。 只是,动态转换需要的类层次结构是多态的(具有至少一个虚函数,即基类)。
来自哪儿呢静态浇铸这种效率增益? 这本书也提到,动态转换是做类型安全的向下转换的首选方法。

Answer 1:

static_cast 本身并不需要RTTI - typeid呢(一样dynamic_cast ),但这是一个完全不同的问题。 大多数类型转换只是告诉编译器“相信我,我知道我在做什么” - dynamic_cast是个例外,它要求编译器检查在运行时可能会失败。 这是一个大的性能差异就在那里!



Answer 2:

更好避免在所有可能的话在类型转换。 这通常是通过相关的代码移动到被不同地用于不同亚型中实现的虚拟方法完成:

class Shape {
public:
    virtual ~Shape() {};
    virtual void announce() = 0;  // And likewise redeclare in Circle and Square.
};

void Circle::announce() {
    cout << "It's a circle!" << endl;
}

void Square::announce() {
    cout << "It's a square!" << endl;
}

// Later...
s->announce();

如果你是一个预先存在的继承层次,你不能改变工作,调查Visitor模式的一个更具扩展性的替代型切换。

更多信息: static_cast 不需要 RTTI,但使用它向下转换可能是不安全的,导致不确定的行为(例如崩溃)。 dynamic_cast是安全的,但缓慢的,因为它会检查(并因此需要)RTTI信息。 老C样式转换甚至比更不安全static_cast ,因为它会悄悄地蒙上跨越完全无关的类型,其中static_cast将与编译时错误对象。



Answer 3:

与静态铸造(和typeid的检查),你不能垂头丧气到中间型(孩子由父亲从派生派生爷爷,你不能从爷爷垂头丧气父亲)的使用是一个小更有限。 没有typeid的检查的static_cast被牺牲性能比较正确性,然后你知道他们怎么说:

他谁牺牲正确性性能值得既不

然后,当然,还有你在哪里,在短短的CPU指令迫切需要且有无处寻找改善的情况下,你是你在做什么是真正安全的,并且您已经meassured(右?),唯一的地方增益性能是使用的static_cast dynamic_cast的,而不是...那么你知道你必须返工的设计,或者你的算法或获得更好的硬件。

通过使用RTTI +的static_cast强加的限制是,你将不能够在以后的时间没有返工所有地方用新的派生类扩展你的代码,你必须用这种伎俩来获得短短CPU指令。 这返工本身可能会花费更多的时间(工程时间更贵),比你获得的CPU时间。 如果,无论如何,致力于向下转换的时间是显着的,那么你的返工设计j_random_hacker建议,这将在设计和性能改进。



Answer 4:

dynamic_cast ,如果你没有做的typeid的检查和演员不能成功将返回NULL。 static_cast会成功(并导致不确定的行为,如最终崩溃)。 这是有可能的速度差。



文章来源: Static cast vs. dymamic cast for traversing inheritance hierarchies