C++ 在访问者模式中使用accept()

C++ 在访问者模式中使用accept(),c++,design-patterns,C++,Design Patterns,我正在研究使用访问者模式。我看到的一些示例建议在每个元素子类中使用accept(Visitor)函数。该函数的想法是否只是为了让访问者能够访问包含多态类型的集合?在这段代码中,我使用访问者进行两种类型的累积,它不需要accept() #包括 #包括 班内项目 { 公众: IntItem(const int a):IntData(a){} int IntData; }; 类双项 { 公众: DoubleItem(const double a):DoubleData(a){} 双重数据; }; 班级

我正在研究使用访问者模式。我看到的一些示例建议在每个元素子类中使用accept(Visitor)函数。该函数的想法是否只是为了让访问者能够访问包含多态类型的集合?在这段代码中,我使用访问者进行两种类型的累积,它不需要accept()

#包括
#包括
班内项目
{
公众:
IntItem(const int a):IntData(a){}
int IntData;
};
类双项
{
公众:
DoubleItem(const double a):DoubleData(a){}
双重数据;
};
班级访客
{
公众:
虚拟无效访问(初始项和项目)=0;
虚拟无效访问(双重项目和项目)=0;
};
类别:公众访客
{
公众:
SumAccumulator():和(0){}
无效访问(初始项和项目)
{
总和+=item.IntData;
}
无效访问(双重项目和项目)
{
总和+=项目数据;
}
双和;
};
类平均值累加器:公共访问者
{
公众:
AverageAccumerator():平均值(0),计数器(0){}
无效访问(初始项和项目)
{
计数器++;
平均值=(计数器-1)*平均值+item.IntData;
平均/=计数器;
}
无效访问(双重项目和项目)
{
计数器++;
平均值=(计数器-1)*平均值+item.DoubleData;
平均/=计数器;
}
整数计数器;
双倍平均;
};
类IntCollection
{
公众:
无效访问(访客和访客)
{
for(无符号整数i=0;i
是的,这就是模式的本质


基本上,如果您有一个相对稳定的
元素
层次结构,它允许您根据需要添加新的
访问者
派生。然后可以在调用者不知道正在操作的元素的具体类型的情况下调用访问者。

我说的不是:

class SumVisitor: public Visitor
{
public:
  SumVisitor() : Sum(0){}
  /*virtual*/void visit(IntElement *e)
  {
    Sum += e->IntData;
  }
  /*virtual*/void visit(DoubleElement *e)
  {
    Sum += e->DoubleData;
  }

  double Sum;
};
为何不:

class IntSumVisitor: public Visitor
{
public:
  SumVisitor() : Sum(0){}
  /*virtual*/void visit(IntElement *e)
  {
    Sum += e->IntData;
  }

  double Sum;
};

class DoubleSumVisitor: public Visitor
{
public:
  DoubleSumVisitor() : Sum(0){}
  /*virtual*/void visit(IntElement *e)
  {
    Sum += e->IntData;
  }

  int Sum;
};

?在一个visitor类中有多个重载会有帮助吗?还是只会引入不必要的依赖关系?

谢谢Andrew。另外,在我看到的所有示例中,它们都有Visit()在同一Visitor类中为多个重载类型创建函数。逻辑似乎无论如何都需要复制,所以为什么不使用单个Visitor创建一个单独的Visitor()功能?我不确定我是否完全理解您的问题,但每个访问者对每个元素类型都有一个
visit
重载的原因是,访问者可以通过元素调用
visitor->visit(此)来发现正在操作的元素的具体类型
。这是一种在没有内置支持的语言中实现双重分派的迂回方式。
class SumVisitor: public Visitor
{
public:
  SumVisitor() : Sum(0){}
  /*virtual*/void visit(IntElement *e)
  {
    Sum += e->IntData;
  }
  /*virtual*/void visit(DoubleElement *e)
  {
    Sum += e->DoubleData;
  }

  double Sum;
};
class IntSumVisitor: public Visitor
{
public:
  SumVisitor() : Sum(0){}
  /*virtual*/void visit(IntElement *e)
  {
    Sum += e->IntData;
  }

  double Sum;
};

class DoubleSumVisitor: public Visitor
{
public:
  DoubleSumVisitor() : Sum(0){}
  /*virtual*/void visit(IntElement *e)
  {
    Sum += e->IntData;
  }

  int Sum;
};