이것은 성능에 대해 너무 걱정하지 않는다는 점에서 약간의 가설입니다. 실제로 어떤 옵션이 실제로 가장 빠르고/가장 효율적인지 궁금하거나, 차이가 전혀 없는지 궁금합니다.더 빠른 방법 : 가상 기반이나 크로스 캐스트를 사용하여 다운 캐스트 할 수 있습니까?
가정하자 나는 방문자 템플릿 다음 코드 오버로드를 지원 한 것을 : 방문자가 궁극적으로 dynamic_cast<>
's의 결과 사용
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);
};
:
#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() {}
이 다음 일반 방문자를 만드는 데 사용됩니다 Visitor
에서 VTarget<T>
까지이며, 이것은 크로스 캐스트입니다.
VTarget<T>
-의 가상베이스를 방문자가 더 이상 직접 상속하지 않아도되도록 구현할 수 있습니다. Visitor :: visit 코드의 dynamic_cast<>
은 가상베이스에서 다운 캐스트가 발생합니다 (Visitor
).
캐스트를 수행 할 때 한 방법이 다른 방법보다 빠릅니까? 또는 가상 기반을 가지고있는 경우에만 크기 패널티가 있습니까?
"캐스트를 수행 할 때 다른 방법보다 한 가지 방법이 더 빠릅니까?" 이에 대한 유일한 현명한 방법은 실제로 측정하는 것입니다. 그 코드는 코드에 따라 다르므로 행운을 빈다. 투표를 종료합니다. –
또한, 방문자의 모든 지점은 캐스팅이 필요 없다는 것입니다. –
@Alexandre이 방문자가 이런 식으로 구현 된 이유는 클래스 계층의 방문자 대상에 대한 종속성이 없다는 것입니다. 그런 식으로 클래스 계층 구조의 일부는 라이브러리 및 클라이언트 코드의 다른 부분에 상주 할 수 있습니다. 이는 기존의 정적 인 방문자가 실제로는 불가능합니다. – Pete