这有点假设,因为我不太担心性能-只是想知道哪个选项实际上通常是最快/最有效的,或者是否没有区别。
假设我有以下代码用于支持重载的访问者模板:
#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<>
从Visitor
到VTarget<T>
的交叉转换。可以实现的另一种方法是使
Visitor
成为VTarget<T>
的虚拟基础-然后MyVisitor
将不再需要直接从Visitor继承。然后,Visitor::visit代码中的
dynamic_cast<>
将导致虚拟基础Visitor
的下调。执行转换时,一种方法是否比另一种方法快?还是您只因为拥有虚拟基地而获得了尺寸上的损失?
最佳答案
好吧,看来跨播方法比虚拟基础方法要快。
一次访问需要1次回退到父类(super class),迭代超过1亿次,因此交叉转换方法花费了30.2747秒,而虚拟基础方法花费了41.3999秒-慢了约37%。
super 类没有过载的后备,交叉广播为10.733秒,虚拟基准为19.9982(慢86%)。
我更想知道dynamic_cast在这两种模式下如何工作。
关于c++ - 更快的是:从虚拟基础向下广播还是从交叉广播?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/6940856/