這是有點假設的,因爲我並不太擔心性能 - 只是想知道哪種選項實際上是最快/最有效的,或者如果沒有任何區別。速度更快:從虛擬基地還是十字路口向下投射?
假設我有一個訪問者模板下面的代碼,支持超載:
#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
向下演變。
執行演員時,其中一種方法比另一種快嗎?或者你是否僅僅因爲擁有虛擬基地而受到懲罰?
「執行演員時,其中一種方法比另一種更快嗎?」回答這個問題的唯一明智的方法是實際衡量。祝你好運,因爲它取決於,錯誤,周圍的代碼。投票結束。 –
另外,訪問者的重點是你不需要投射。 –
@Alexandre以這種方式實現此訪問者的原因是您沒有對類層次結構中訪問者目標的依賴關係。這樣,類層次結構的一部分可以駐留在庫中,而另一部分則駐留在客戶端代碼中 - 對於傳統的靜態訪問者來說並不是真正可行的。 – Pete