これは、私がパフォーマンスについてあまり心配していないので、多少仮説的です。実際にどのオプションが実際には最も速く/最も効率的かを疑問に思っています。速いもの:仮想ベースまたはクロスキャストからのダウンキャスト?
は、私が過負荷をサポートしている訪問者のテンプレートの次のコードがあるとします。
#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>
まではクロスキャストです。
の仮想ベースをVTarget<T>
-MyVisitor
にすることは、Visitorから直接継承する必要はありません。 Visitor :: visitコードのdynamic_cast<>
は、仮想ベースからのダウンキャストの結果となります。Visitor
。
キャストを実行するとき、1つの方法が他の方法より高速ですか?それとも、仮想ベースを持っているためにサイズのペナルティを受けるだけですか?
"キャストを実行するとき、一方の方法が他の方法より速くなっていますか?"これに答える唯一の賢明な方法は、実際に測定することです。そのことを幸運に思うのは、コードが間違っているからです。投票を終了する。 –
また、訪問者の全体のポイントは、キャストする必要がないということです。 –
@Alexandreこの訪問者がこのように実装される理由は、クラス階層の訪問者ターゲットに依存しないことです。こうすることで、クラス階層の一部がライブラリ内に存在し、クライアントコード内の別の部分が常駐することができます。 – Pete