Static cast vs. dymamic cast for traversing inheritance hierarchies

时光毁灭记忆、已成空白 提交于 2019-12-04 07:01:13

static_cast per se DOESN'T need RTTI -- typeid does (as does dynamic_cast), but that's a completely different issue. Most casts are just telling the compiler "trust me, I know what I'm doing" -- dynamic_cast is the exception, it asks the compiler to check at runtime and possibly fail. That's the big performance difference right there!

It's much better to avoid switching on types at all if possible. This is usually done by moving the relevant code to a virtual method that is implemented differently for different subtypes:

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();

If you are working with a pre-existing inheritance hierarchy that you can't change, investigate the Visitor pattern for a more extensible alternative to type-switching.

More info: static_cast does not require RTTI, but a downcast using it can be unsafe, leading to undefined behaviour (e.g. crashing). dynamic_cast is safe but slow, because it checks (and therefore requires) RTTI info. The old C-style cast is even more unsafe than static_cast because it will quietly cast across completely unrelated types, where static_cast would object with a compile-time error.

With the static cast (and typeid check) you cannot downcast to an intermediate type (child derives from father derives from grandfather, you cannot downcast from grandfather to father) the usage is a little more limited. static_cast without the typeid check is sacrificing correctness for perfomance, and then you know what they say:

He who sacrifices correctness for performance deserves neither

Then of course, there are situations where you are in desperate need of a few CPU instructions and there is nowhere else to look for improvements and you are actually safe on what you are doing and you have meassured (right?) that the only place to gain performance is using static_cast instead of dynamic_cast... then you know you must rework your design, or your algorithms or get better hardware.

The restrictions you impose by using rtti + static_cast is that you will not be able to extend your code with new derived classes at a later time without reworking all places where you have used this trick to gain just a few CPU instructions. That reworking itself will probably take more time (engineering time that is more expensive) than the CPU time you have obtained. If, at any rate, the time devoted to downcasts is noticeable, then rework your design as j_random_hacker suggests, it will improve both in design and performance.

dynamic_cast would return NULL if you hadn't done the typeid check and the cast couldn't succeed. static_cast would succeed (and lead to undefined behavior, such as an eventual crash). That's likely the speed difference.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!