Visitor 패턴을 가지고 놀고 있는데 컴파일되는 다음과 같은 코드가 있습니다.
class DerivedVisitee;
class Visitor
{
public:
void visit(DerivedVisitee &v);
};
class Visitee
{
public:
virtual void accept(Visitor &v) = 0;
};
class DerivedVisitee : public Visitee
{
public:
void accept(Visitor &v) { v.visit(*this); }
};
의 visit
모든 자손에 대해 기본 방법 을 제공하고 싶습니다 Visitee
. 따라서 다음을 시도했습니다.
class DerivedVisitee;
class Visitor
{
public:
void visit(DerivedVisitee &v);
};
class Visitee
{
public:
virtual void accept(Visitor &v) { v.visit(*this); } // added implementation here
};
class DerivedVisitee : public Visitee
{
// removed overridden method
};
그러나 'void Visitor::visit(DerivedVisitee &)' : cannot convert argument 1 from 'Visitee' to 'DerivedVisitee &'
(MSVC) 에서는 컴파일이 실패합니다 . 이런 일이 발생하는 이유와 내가하려는 작업을 수행하는 올바른 방법이 무엇인지 설명해 주시겠습니까?
편집 : 개체에서만 Visitor::visit
작업해야합니다 DerivedVisitee
. 다른 말로하면 Visitor::visit
.NET의 다른 자손에 대해 다른 구현으로 여러 오버로드 된 메서드 를 사용하려고합니다 Visitee
.
기본적인 대답은 순수 객체 지향 코드에서는 불가능 하다는 것입니다.
본질적으로 방문자 패턴은 visit
파생 된 유형으로 전달하는 것이며 , 해당 Visitee
유형에서는 알 수 없습니다 (런타임 속성 임).
C ++에는 CRTP 라는 패턴이 있습니다 .
template <typename Derived, typename Base>
class VisiteeHelper: public Base {
public:
virtual void accept(Visitor& v) override {
Derived& d = static_cast<Derived&>(*this);
v.visit(d);
}; // class VisiteeHelper
그리고 다음에서 파생 할 수 있습니다.
// And there we see the "Curiously Recurring" part:
class DerivedVisitee: public VisiteeHelper<DerivedVisitee, Visitee> {
}; // class DerivedVisitee
class MoreDerivedVisitee: public VisiteeHelper<MoreDerivedVisitee, DerivedVisitee> {
}; // MoreDerivedVisitee
단순하지 않은 상용구 또는 스마트 한 (하지만 잠재적으로 혼란스러운) CRTP 솔루션을 선호하는지 여부를 결정하는 것은 귀하에게 달려 있습니다.
개인적으로 accept
(const-ness에 오버로딩하여 유형 당 최대 4 개의) 오버로드가 여러 개있는 경우 가 아니면 신경 쓰지 않습니다. accept
손 으로 쓰는 것만큼이나 많은 작업이 필요 하며, 간단하고 즉시 이해할 수 있습니다.
이 기사는 인터넷에서 수집됩니다. 재 인쇄 할 때 출처를 알려주십시오.
침해가 발생한 경우 연락 주시기 바랍니다[email protected] 삭제
몇 마디 만하겠습니다