带有子类节点上的访问者的C ++访问者模式失败"是"关系

时间:2017-02-10 17:03:36

标签: c++ inheritance design-patterns visitor-pattern

首先,对不起,如果这是重复的话。我没有看到类似的东西。

我熟悉访问者模式,并且我试图为我的图表上的访问者添加更多灵活性。如果我有节点类A,B,C,SubB(继承B),我希望能够有一个接受B节点的访问者,并且会在不知道它们的情况下自动接受SubB节点(定义accept())。 / p>

显而易见的好处是我可以整天进行子类化,并且访问者不需要关心这些类型的访问定义。

我有以下代码和结果。 如您所见,这是它将访问的节点。

new Node(),
new ANode(),
new BNode(),
new CNode(),
new BNode(),
new SubBNode()

基本上,CountVisitor正确地报告它找到了2个B,我理解为什么。 CountVisitor.visit(SubB&)未被覆盖,将改为重定向到Visitor.visit(SubB&),从而跳过计数。但是,我想要报告3(2 Bs + 1 SubB)的功能,因为SubB"是" B.我已经考虑过这个问题,而我却无法弄清楚如何让类型系统做到这一点。我应该如何重新排列以实现该功能?如果能保持"是一个"我也会对替代模式持开放态度。关系,但我认为如果这个障碍得到解决,访客将是完美的。

#include <iostream>
#include <string>
#include <vector>

using namespace std;

class Visitor;

class Node
{
  public:
  vector<Node*> children;
  virtual void accept(Visitor&);
};

class ANode : public Node
{
  public:
  virtual void accept(Visitor&);

};
class BNode : public Node
{
  public:
  virtual void accept(Visitor&);
};
class CNode : public Node
{
  public:
  virtual void accept(Visitor&);
};

//-- try inheritance

class SubBNode: public BNode
{
  public:
  virtual void accept(Visitor&);
};

//--

class Visitor 
{
  public:
  virtual void visit(Node& n);
  virtual void visit(ANode& n);
  virtual void visit(BNode& n);
  virtual void visit(CNode& n);
  virtual void visit(SubBNode& n);
};

class CountVisitor : public Visitor
{
  public:
  virtual void visit(BNode& n);

  int count = 0;
  void print();
};
//---------------------------------------------

void Node::accept(Visitor& v){
  cout << __PRETTY_FUNCTION__ << endl;
  v.visit(*this);
}
void ANode::accept(Visitor& v){
  cout << __PRETTY_FUNCTION__ << endl;
  v.visit(*this);
}
void BNode::accept(Visitor& v){
  cout << __PRETTY_FUNCTION__ << endl;
  v.visit(*this);
}
void CNode::accept(Visitor& v){
  cout << __PRETTY_FUNCTION__ << endl;
  v.visit(*this);
}
void SubBNode::accept(Visitor& v){
  cout << __PRETTY_FUNCTION__ << endl;
  v.visit(*this);
}
// -----
void Visitor::visit(Node& n){
  cout << __PRETTY_FUNCTION__ << "\t\tDEFAULT" << endl;
}
void Visitor::visit(ANode& n){
  cout << __PRETTY_FUNCTION__ << "\t\tDEFAULT" << endl;
}
void Visitor::visit(BNode& n){
  cout << __PRETTY_FUNCTION__ << "\t\tDEFAULT" << endl;
}
void Visitor::visit(CNode& n){
  cout << __PRETTY_FUNCTION__ << "\t\tDEFAULT" << endl;
}
void Visitor::visit(SubBNode& n){
  cout <<  __PRETTY_FUNCTION__ << "\t\tDEFAULT" << endl;
}
// -----
void CountVisitor::visit(BNode& n){
  count++;
  cout << __PRETTY_FUNCTION__ << "\t\tSPECIAL" << endl;
}
void CountVisitor::print(){
  cout << "CountVisitor Found Bs: "<< count << endl;
}


// ====================================================

int main() {

  cout << "======FLAT TEST======" << endl;
  vector<Node*> nodes = {
    new Node(),
    new ANode(),
    new BNode(),
    new CNode(),
    new BNode(),
    new SubBNode()
  };

  cout << "--DEFAULT--" << endl;
  Visitor v1;
  for( Node* n : nodes ){
    n->accept(v1);
  }

  cout << "--COUNT--" << endl;
  CountVisitor cv1;
  for( Node* n : nodes ){
    n->accept(cv1);
  }
  cv1.print();
  return 0;
}

结果

======FLAT TEST======
--DEFAULT--
virtual void Node::accept(Visitor&)
virtual void Visitor::visit(Node&)      DEFAULT
virtual void ANode::accept(Visitor&)
virtual void Visitor::visit(ANode&)     DEFAULT
virtual void BNode::accept(Visitor&)
virtual void Visitor::visit(BNode&)     DEFAULT
virtual void CNode::accept(Visitor&)
virtual void Visitor::visit(CNode&)     DEFAULT
virtual void BNode::accept(Visitor&)
virtual void Visitor::visit(BNode&)     DEFAULT
virtual void SubBNode::accept(Visitor&)
virtual void Visitor::visit(SubBNode&)      DEFAULT
--COUNT--
virtual void Node::accept(Visitor&)
virtual void Visitor::visit(Node&)      DEFAULT
virtual void ANode::accept(Visitor&)
virtual void Visitor::visit(ANode&)     DEFAULT
virtual void BNode::accept(Visitor&)
virtual void CountVisitor::visit(BNode&)        SPECIAL
virtual void CNode::accept(Visitor&)
virtual void Visitor::visit(CNode&)     DEFAULT
virtual void BNode::accept(Visitor&)
virtual void CountVisitor::visit(BNode&)        SPECIAL
virtual void SubBNode::accept(Visitor&)
virtual void Visitor::visit(SubBNode&)      DEFAULT
CountVisitor Found Bs: 2

1 个答案:

答案 0 :(得分:1)

您可以添加其他图层,例如:

{{1}}

Demo