5

考虑以下层次结构:

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);
}

我不能使用经典的访问者模式解决方案,因为仅在其中一个参数上调用了接受方法。

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

4

1 回答 1

8

我为您创建了“三重”调度模式: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 << "11\n"; }
    virtual void Visit(Derived1 & param1, Derived2 &param2) { cout << "12\n"; }
    virtual void Visit(Derived2 & param1, Derived1 &param2) { cout << "21\n"; }
    virtual void Visit(Derived2 & param1, Derived2 &param2) { cout << "22\n"; }
};

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);
}

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

于 2012-07-08T22:15:35.647 回答