是可能的访客在c++中操作多个项目?



我正在尝试添加一个访问者到现有的图书馆。访问者必须能够访问来自不同项目的一些类。

假设我的解决方案有以下项目:ProjectA,ProjectB,它们分别包含一个类:NodeA,NodeB。由于访问者只是类成员在类之外的实现,我认为它的依赖关系将不允许它被放置在另一个项目中。因此,如果我想创建一个访问者,可以访问NodeANodeB对象,我不能使用一个简单的访问者。

这个评估正确吗?

我正在考虑一些解决方案来克服这个问题。

  1. 将其中一个类移动到另一个项目并在那里实现visitor(这不是一个可行的解决方案)。
  2. 添加一个额外的间接。为每个项目的访问者实现创建一个类。并创建一个"首席访问者"。

我错过了什么吗?有更好的方法吗?

下面是我的访问者实现。请注意,为了简单起见,我删除了标题保护符。

/// --- Node.h in project A ---
class Visitor;
class Node {
public:
Node() = default;
virtual ~Node() = default;
virtual void accept(Visitor & v) = 0;
};
/// --- NodeA.h  in project A ---
#include "Visitor.h"
class NodeA : public Node {
public:
void accept(Visitor & v);
};
/// --- NodeB.h  in project B ---
#include "Visitor.h"
class NodeB : public Node {
public:
void accept(Visitor & v);
};
/// --- Visitor.h ---
#include "Node.h"
class NodeA;
class NodeB;
class Visitor {
public:
Visitor() = default;
virtual ~Visitor() = default;
virtual void visit(const Node & node);
virtual void visit(const NodeA & node);
virtual void visit(const NodeB & node);
};
// --- Visitor.cpp ---
#include "Visitor.h"
#include "NodeA.h"
void Visitor::visit(const Node & node)
{
// implementation
}
void Visitor::visit(const NodeA & node)
{
// implementation
}
void Visitor::visit(const NodeB & node)
{
// implementation
}

如果NodeANodeB之间除了能够接受访问者并将其存储在a(例如std::vector<std::unique_ptr<Node>>)中之外没有任何共同之处,请考虑使用std::variant

代码看起来像这样:

#include <variant>
#include <iostream>
#include <vector>
class NodeA {};
class NodeB {};
using Node = std::variant<NodeA, NodeB>;

class Visitor
{
public:
void operator()(NodeA & node) 
{
std::cout << "encountered A" << std::endl;
}

void operator()(NodeB & node) 
{
std::cout << "encountered B" << std::endl;
}
};

int main() 
{
std::vector<Node> nodes;
nodes.emplace_back(NodeA{});
nodes.emplace_back(NodeA{});
nodes.emplace_back(NodeB{});
nodes.emplace_back(NodeA{});
nodes.emplace_back(NodeB{});
nodes.emplace_back(NodeB{});

Visitor visitor;

for (auto & node : nodes)
{
std::visit(visitor, node);
}
}

这样NodeA,NodeB和访问者的实现基本上是解耦的。

如果我将访问者接口类放在与Node相同的项目中,并且只在派生节点头中使用它,我可以将派生访问者类放在不同的项目中,这将取决于所有内容(基节点和派生节点以及基访问者)。visit方法将被动态地分配给适当的visitor实例。

最新更新