2017-08-09 28 views
-1

我有一个定向的非循环图数据结构,其中有多种类型的父节点和叶子。有一个函数(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; 
    } 

} 
+0

与其取消开关语句,您可以分别编写用于处理每个“case”的函数,然后您的代码将看起来更清晰。 – AndyG

回答

4

你可以使用访问者模式为。您可以将一个Apply函数添加到您的Node类中,并在每个派生类中重写它以调用IVisitor接口中的匹配访问方法。然后你为每个操作实现一个具体的访问者。假设Node类型是稳定的,如果你不想在Node派生类中添加所有的操作,这可能是一个好方法。搜索网页,如果你需要代码。

+0

在我的名声中,我没有看到任何倒退的问题。我不认为有可能知道,所以不要假设... – Phil1970