【发布时间】:2012-07-06 15:59:56
【问题描述】:
考虑以下层次结构:
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 个参数重载 Visit,不超过 2 个)。
【问题讨论】:
-
您会说您面临的是在 C++ 中模拟 multiple dispatch 吗?
-
@Luc Danton:嗯,我想是的。我知道查找表解决方案,但我试图避免它(我的基类是纯虚拟的,我想保持这种方式)。 dynamic_cast 解决方案有效,但我需要几个这样的控件,因为调度发生在对象对上。无论如何,如果您对这些解决方案有任何建议,请告诉我。我很高兴听到您的意见。
-
VisitorInterfaceMultiple需要做什么?依次调用两个accept方法?在传递另一个时调用一个? -
@Mark B:其实是一种碰撞检测方法。因此应根据参数类型选择正确的碰撞方法。我认为它不能顺序调用两种方法。必须同时评估这两个参数。
标签: c++ visitor-pattern double-dispatch