我有一个定向的非循环图数据结构,其中有多种类型的父节点和叶子。有一个函数(BuildGraph
),它发出这个图,另一个处理它(ProcessGraph
)。这两个函数分别位于.cpp
文件中,但定义数据结构的文件.h
包含在两者中。如果数据类无法访问处理类,我该如何消除动态转换和切换?
ProcessGraph
有许多switch
语句,我不能用虚函数替换它们,因为图节点无法访问它们的处理方式。我想消除那些switch
声明,但我不知道如何。在C++中解决类似问题的首选方法是什么?
的数据结构:
enum NodeType {
GROUP_TYPE_1 = 1,
GROUP_TYPE_2 = 2,
LEAF_TYPE_1 = 3,
LEAF_TYPE_2 = 4,
LEAF_TYPE_3 = 5
};
struct Node {
const NodeType type;
Node(NodeType _type) : type(_type) {}
virtual ~Node() {}
};
struct Group {
std::vector<std::shared_ptr<Node>> nodes;
};
struct GroupNode1 : public Node, public Group {
GroupNode1() : Node(GROUP_TYPE_1) {}
/*...*/
};
struct GroupNode2 : public Node, public Group {
GroupNode2() : Node(GROUP_TYPE_2) {}
/*...*/
};
struct LeafNode1 : public Node {
LeafNode1() : Node(LEAF_TYPE_1) {}
/*...*/
};
struct LeafNode2 : public Node {
LeafNode2() : Node(LEAF_TYPE_2) {}
/*...*/
};
struct LeafNode3 : public Node {
LeafNode3() : Node(LEAF_TYPE_3) {}
/*...*/
};
struct Graph {
std::shared_ptr<Node> root;
/*...*/
};
BuildGraph:
Graph g;
// create a diamond shape
std::shared_ptr<GroupNode2> root = std::make_shared<GroupNode2>();
g.root = root;
std::shared_ptr<GroupNode1> c1 = std::make_shared<GroupNode1>();
root->nodes.push_back(c1);
std::shared_ptr<GroupNode2> c2 = std::make_shared<GroupNode2>();
root->nodes.push_back(c2);
std::shared_ptr<Node> l1 = std::make_shared<LeafNode2>();
c1->nodes.push_back(l1);
c2->nodes.push_back(l1);
return g;
ProcessGraph:
void ProcessGraph(std::shared_ptr<Node> root) {
switch (root->type) {
case NodeType::GROUP_TYPE_1:
case NodeType::GROUP_TYPE_2:
{
Group* g = dynamic_cast<Group*>(root.get());
for (std::shared_ptr<Node>& node : g->nodes) {
ProcessGraph(node);
}
switch (root->type) {
/* for each group type */
}
}
break;
case NodeType::LEAF_TYPE_1:
{
LeafNode1* l = dynamic_cast<LeafNode1*>(root.get());
/* ... */
}
break;
case NodeType::LEAF_TYPE_2:
{
LeafNode2* l = dynamic_cast<LeafNode2*>(root.get());
/* ... */
}
break;
case NodeType::LEAF_TYPE_3:
{
LeafNode3* l = dynamic_cast<LeafNode3*>(root.get());
/* ... */
}
break;
}
}
与其取消开关语句,您可以分别编写用于处理每个“case”的函数,然后您的代码将看起来更清晰。 – AndyG