具有多个可访问参数的C++访客模式

Visitor Pattern in C++ with multiple visitable parameters

本文关键字:C++ 访客 模式 参数 访问      更新时间:2023-10-16

考虑以下层次结构:

class Base
{
   virtual void Method() = 0;
   virtual void Accept(Visitor *iVisitor) = 0;
};
class Derived1: public Base
{
   virtual void Method(){//impl}
   virtual void Accept(Visitor *iVisitor)
   {
        iVisitor->Visit(this);
   }
};
class Derived2: public Base
{
   virtual void Method(){//impl}
   virtual void Accept(Visitor *iVisitor)
   {
       iVisitor->Visit(this);
   }
};

和访客类:

class VisitorInterface
{
    virtual void Visit(Derived1 * param);
    virtual void Visit(Derived2 * param);
}
class Visitor: public VisitorInterface
{
    void Visit(Derived1 * param){}
    void Visit(Derived2 * param){}
}

通常,当重载方法取决于参数类型时,我使用访问者模式来实现双重调度,但我只有指向基类的指针。

例如:

void foo(Visitor *visitorPtr, Base * basePtr)
{
    basePtr->Accept(visitorPtr);    
} 

我认为这是实现双重调度的唯一方法,因为虚函数的动态绑定应该只发生在调用该方法的对象上,而不是发生在它的参数(派生类型)上。

现在我遇到了一个新情况,我需要一种对多个参数进行重载的 Visit 方法。像这样:

class VisitorInterfaceMultiple
{
    virtual void Visit(Derived1 * param1, Derived2 * param2);
    virtual void Visit(Derived2 * param1, Derived3 *param2);
}

我无法使用经典的访客模式解决方案,因为仅对其中一个参数调用 accept 方法。

我的问题是:是否存在任何类似的访客模式解决方案或类似的东西,我可以在这种情况下使用?(我需要使用确切的 2 个参数重载访问,不超过 2 个)。

我为您创建了"三重"调度模式:http://ideone.com/FoXNW这很容易。主要部分如下:

class Derived1;
class Derived2;
class Visitor;
class Base
{
public:
   virtual void Accept(Visitor &iVisitor, Base& param1) = 0;
   virtual void Accept(Visitor &iVisitor, Derived1& param2) = 0;
   virtual void Accept(Visitor &iVisitor, Derived2& param2) = 0;
};
class Visitor
{
public:
    virtual void Visit(Derived1 & param1, Derived1 &param2) { cout << "11n"; }
    virtual void Visit(Derived1 & param1, Derived2 &param2) { cout << "12n"; }
    virtual void Visit(Derived2 & param1, Derived1 &param2) { cout << "21n"; }
    virtual void Visit(Derived2 & param1, Derived2 &param2) { cout << "22n"; }
};
class Derived1: public Base
{
public:
   virtual void Accept(Visitor &iVisitor, Base& param1) 
   { param1.Accept(iVisitor, *this); }
   virtual void Accept(Visitor &iVisitor, Derived1& param2)
   { iVisitor.Visit(*this, param2); }
   virtual void Accept(Visitor &iVisitor, Derived2& param2)
   { iVisitor.Visit(*this, param2); }
};
class Derived2: public Base
{
public:
   virtual void Accept(Visitor &iVisitor, Base& param1) 
   { param1.Accept(iVisitor, *this); }
   virtual void Accept(Visitor &iVisitor, Derived1& param2)
   { iVisitor.Visit(*this, param2); }
   virtual void Accept(Visitor &iVisitor, Derived2& param2)
   { iVisitor.Visit(*this, param2); }
};
void Visit(Visitor& visitor, Base& param1, Base& param2)
{
   param2.Accept(visitor, param1);
}

请注意,Dederd1 和 Derived2 的实现实际上是相同的。如果您有更多派生内容,则可以将其包含在宏中。