私は有向非循環グラフのデータ構造を持っています。そこには、複数のタイプの親ノードとリーフがあります。このグラフを出力する関数(BuildGraph
)があり、他の関数はそれを処理します(ProcessGraph
)。 2つの機能は別々のファイル.cpp
にありますが、データ構造が定義されている.h
ファイルは両方に含まれています。データクラスが処理クラスにアクセスできない場合、動的キャストとスイッチを削除するにはどうすればよいですか?
ProcessGraph
には多くの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;
}
}
switch文を削除するのではなく、それぞれの 'case'を扱うための関数を別々に書くことができます。 – AndyG