First, sorry if this is a duplicate. I didn't see anything similar though.
I'm familiar with the visitor pattern and I'm trying to add a little bit more flexibility for the visitor on my graph. If I have node classes A,B,C, SubB (inherits B), I would like to be able to have a visitor that accepts B nodes and will automatically accept SubB nodes without knowing about them (defining the accept()).
The obvious benefit is that I can subclass all day and the visitor doesn't need to care about the defining a visit for those types.
I have code and results to demonstrate below. As you can see, here are the nodes it will visit.
new Node(), new ANode(), new BNode(), new CNode(), new BNode(), new SubBNode()
Basically the CountVisitor correctly reports it found 2 Bs, and I understand why. CountVisitor.visit(SubB&) isn't overridden and will redirect to Visitor.visit(SubB&) instead, thus skipping the count. However, I would like the functionality where it reports 3 ( 2 Bs + 1 SubB ) because SubB "is a" B. I've thought about this and I just can't figure out how to make the type system do it. How should I rearrange things to achieve that functionality?
#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;
}
RESULTS
======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
Aucun commentaire:
Enregistrer un commentaire