访问者在子类节点上的 C++ 访问者模式失去 "is a" 关系

C++ Visitor Pattern with visitor over subclassed nodes loses "is a" relationship

首先,抱歉,如果这是重复的。不过我没有看到任何类似的东西。

我熟悉访问者模式,我正在尝试为图表上的访问者增加一点灵活性。如果我有节点 类 A、B、C、SubB(继承 B),我希望能够有一个访问者接受 B 节点并自动接受 SubB 节点而不知道它们(定义接受( )).

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

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

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 "is a" B。我已经考虑过这个,但我只是不知道如何让类型系统做到这一点。我应该如何重新安排事物以实现该功能?如果能保持 "is a" 关系,我也愿意接受其他模式,但我确实认为如果这个问题得到解决,访问者将是完美的。

#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

您可以添加一个附加层,例如:

template <typename F>
class FunctorVisitor : public Visitor
{
public:
    explicit FunctorVisitor (F& f) : f(f) {}

    virtual void visit(Node& n) override { f(n);}
    virtual void visit(ANode& n) override { f(n);}
    virtual void visit(BNode& n) override { f(n);}
    virtual void visit(CNode& n) override { f(n);}
    virtual void visit(SubBNode& n) override { f(n);}
private:
    F& f;
};


class CountVisitor
{
public:
    void operator() (const Node& n) const {
        cout << __PRETTY_FUNCTION__ << "\t\tDefault" << endl;
    }
    void operator() (const BNode& n) {
        count++;
        cout << __PRETTY_FUNCTION__ << "\t\tSPECIAL" << endl;
    }

    int count = 0;
    void print() const {
        cout << "CountVisitor Found Bs: "<< count << endl;
    }
};

Demo