什么更快:从虚拟基地向下投射还是交叉投射?

What's faster: down-cast from virtual base or cross-cast?

本文关键字:虚拟 什么      更新时间:2023-10-16

这有点假设,因为我不太担心性能-只是想知道哪个选项实际上是最快/最有效的,或者如果没有任何区别。

假设我有一个支持重载的访问者模板的下面代码:
#define IMPLEMENT_VISITOR_WITH_SUPERCLASS(superclass)  
    typedef superclass visitor_super_t;     
    virtual void visit(Visitor& v) { v.visit(*this); }
//-----------------------------------------------------------------------------
// Implementation detail:
// Selective dispatcher for the visitor - required to handle overloading.
//
template <typename T>
struct VisitorDispatch {
    static void dispatch(Visitor* v, T* t) { v->visit(*t); }
};
// Specalization for cases where dispatch is not defined
template <> struct VisitorDispatch<void> {
    static void dispatch(Visitor* v, void* t) { throw std::bad_cast(""); }
};
//-----------------------------------------------------------------------------
// Derive visitors from this and 'Visitor'.
template <typename T>
class VTarget
{
public:
    // Don't really need a virtual dtor.
    virtual void dispatch(T& t) = 0;
};
//-----------------------------------------------------------------------------
class Visitor
{
public:
    virtual ~Visitor() = 0;
    template <typename T>
    void visit(T& t) {
        typedef VTarget<T> target_t;
        target_t* tgt = dynamic_cast<target_t*>(this);
        if (tgt) {
            tgt->dispatch(t);
        }
        else {
            // Navigate up inhertiance hierarchy.
            // requires 'super' to be defined in all classes in hierarchy
            // applicable to this visitor.
            typedef typename T::visitor_super_t super;
            super* s = static_cast<super*>(&t);
            VisitorDispatch<super>::dispatch(this, s);
        }
    }
};
//-----------------------------------------------------------------------------
inline Visitor::~Visitor() {}

然后用于创建通用访问者:

class CommonBase { 
    IMPLEMENT_VISITOR_WITH_SUPERCLASS(void)
    virtual ~CommonBase() = 0;
};
class A : public CommonBase {
    IMPLEMENT_VISITOR_WITH_SUPERCLASS(CommonBase)
};
class B : public CommonBase {
    IMPLEMENT_VISITOR_WITH_SUPERCLASS(CommonBase)
};
class MyVisitor
    : public Visitor
    , public VTarget<CommonBase>
    , public VTarget<A>
    , public VTarget<B>
{
public:
    virtual void dispatch(CommonBase& obj);
    virtual void dispatch(A& obj);
    virtual void dispatch(B& obj);
};

使用访客最终得到dynamic_cast<>VisitorVTarget<T>,这是一个交叉铸造。

可以实现的另一种方法是使Visitor成为VTarget<T>的虚拟基- MyVisitor将不再需要直接从Visitor继承。然后,Visitor::visit代码中的dynamic_cast<>将导致从虚基Visitor向下强制转换。

执行强制类型转换时,一个方法比另一个方法快吗?还是只会因为拥有虚拟基地而受到大小惩罚?

嗯,看起来交叉转换方法比虚基方法快。

对于需要1次回滚到超类的访问,在100000000次迭代中,交叉转换方法耗时30.2747秒,虚拟基方法耗时41.3999秒,大约慢37%。

在没有回滚到超类重载的情况下,交叉转换耗时10.733秒,虚拟基类耗时19.9982秒(慢了86%)。

我更想知道dynamic_cast在这两种模式下是如何操作的,真的