访问者在子类节点上的 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;
}
};
首先,抱歉,如果这是重复的。不过我没有看到任何类似的东西。
我熟悉访问者模式,我正在尝试为图表上的访问者增加一点灵活性。如果我有节点 类 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;
}
};