避免使用dynamic_cast进行向下转型到原始类型

5

如何安全地向下转型(即在失败时返回null)到底层对象的确切类型,而不会承担dynamic_cast的性能损失,并且不必在我使用的每个类中都放置支持代码?


2
如果这是可能的,那么为什么dynamic_cast没有实现这个方法呢? - Konrad Rudolph
@KonradRudolph dynamic_cast 更加强大。这本质上是一个特殊用例。 - Dan
@KonradRudolph 这只用于在需要将基指针转换为底层对象实际上是的完全相同类型时使用(即不涉及任何中间类)。 - Seth Carnegie
你有测量过当操作数恰好是正确类型时,使用 dynamic_cast 的代价吗? - Alan Stokes
@AlanStokes 是的,答案里有。 - Dan
显示剩余2条评论
1个回答

4

dynamic_cast会遍历整个继承树来查看您想要的转换是否可能。如果您只想要将对象直接向下转换为与其相同的类型,并且您不需要跨越虚拟继承进行转换,或者将对象转换为其实际类型的基类,则以下代码将起作用:

template<class To>
struct exact_cast
{
    To result;

    template<class From>
    exact_cast(From* from)
    {
        if (typeid(typename std::remove_pointer<To>::type) == typeid(*from))
            result = static_cast<To>(from);
        else
            result = 0;
    }

    operator To() const
    {
        return result;
    }
};

语义与其他转换操作符完全相同,即
Base* b = new Derived();
Derived* d = exact_cast<Derived*>(b);

编辑:我已经在我正在工作的项目上进行了测试。我使用QueryPerformanceCounter得到的结果是:
dynamic_cast:83,024,197
exact_cast:78,366,879
这是一个5.6%的加速。这适用于非平凡的CPU绑定代码。(它不执行I/O操作)


14
这是否有任何证据表明这比使用dynamic_cast更有效? - Oliver Charlesworth
5
为什么要使用类而不是函数? - avakar
@OliCharlesworth:如果获取“typeinfo”只需要几次解引用,没有大量计算涉及,那么它可能更有效率。 - Matthieu M.
2
在我的测试中,针对在堆上构造多态对象并将其分配给基类指针,强制转换为派生类并释放它(使用gcc 4.7.1上的-Ofast优化级别),该代码似乎比dynamic_cast快了0.05秒,迭代次数为4,000,000次。 - Seth Carnegie
2
@Nicol Bolas:这大概是OP所指的“你想要的只是将对象直接向下转换为与其类型相同的类型”。这里“相同”意味着你只能向下转换为最派生的对象类型,而不能向中间基类转换。当然,这极大地限制了此转换的可用性。 - AnT stands with Russia
显示剩余3条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接