【问题标题】:Cyclic dependency between header files头文件之间的循环依赖
【发布时间】:2011-01-06 12:56:33
【问题描述】:

我正在尝试实现具有两个类的树状结构:TreeNode。问题是我想从每个类中调用另一个类的函数,所以简单的前向声明是不够的。

我们来看一个例子:

Tree.h:

#ifndef TREE_20100118
#define TREE_20100118

#include <vector>
#include "Node.h"

class Tree
{
    int counter_;
    std::vector<Node> nodes_;

public:

    Tree() : counter_(0) {}

    void start() {
        for (int i=0; i<3; ++i) {
            Node node(this, i);
            this->nodes_.push_back(node);
        }
        nodes_[0].hi();    // calling a function of Node
    }

    void incCnt() {
        ++counter_;
    }

    void decCnt() {
        --counter_;
    }

};

#endif /* TREE_20100118 */

Node.h:

#ifndef NODE_20100118
#define NODE_20100118

#include <iostream>
//#include "Tree.h"

class Tree;    // compile error without this

class Node
{
    Tree * tree_;
    int id_;

public:

    Node(Tree * tree, int id) : tree_(tree), id_(id)
    {
//      tree_->incCnt();    // trying to call a function of Tree
    }

    ~Node() {
//      tree_->decCnt();    // problem here and in the constructor
    }

    void hi() {
        std::cout << "hi (" << id_ << ")" << endl;
    }

};

#endif /* NODE_20100118 */

调用树:

#include "Tree.h"
...
Tree t;
t.start();

这只是一个简单的例子来说明问题。所以我想要的是从Node 对象调用Tree 的函数。

更新 #1: 感谢您的回答。我试图像在 Java 中那样解决这个问题,即每个类只使用一个文件。看来我得开始分离 .cpp 和 .h 文件了……

更新 #2: 在下面,按照提示,我也粘贴了完整的解决方案。谢谢,问题解决了。

【问题讨论】:

    标签: c++ header cyclic-dependency


    【解决方案1】:

    在头文件中,前向声明成员函数:

    class Node
    {
        Tree * tree_;
        int id_;
    
    public:
        Node(Tree * tree, int id);
        ~Node();
        void hi();
    };
    

    在包含所有必需标头的单独 .cpp 文件中,定义它们:

    #include "Tree.h"
    #include "Node.h"
    
    Node::Node(Tree * tree, int id) : tree_(tree), id_(id)
    {
      tree_->incCnt();
    }
    
    Node::~Node() 
    {
      tree_->decCnt();
    }
    
    etc
    

    这也有保持你的标题可读的效果,所以很容易一目了然地看到一个类的接口。

    【讨论】:

      【解决方案2】:

      按照提示,这里是完整的解决方案。

      Tree.h:

      #ifndef TREE_20100118
      #define TREE_20100118
      
      #include "Node.h"
      #include <vector>
      
      class Tree
      {
          int counter_;
          std::vector<Node> nodes_;
      
      public:
      
          Tree();
          void start();
          void incCnt();
          void decCnt();
      };
      
      #endif /* TREE_20100118 */
      

      Tree.cpp:

      #include "Tree.h"
      #include "Node.h"
      
      Tree::Tree() : counter_(0) {}
      
      void Tree::start()
      {
          for (int i=0; i<3; ++i) {
              Node node(this, i);
              this->nodes_.push_back(node);
          }
          nodes_[0].hi();    // calling a function of Node
      }
      
      void Tree::incCnt() {
          ++counter_;
      }
      
      void Tree::decCnt() {
          --counter_;
      }
      

      Node.h:

      #ifndef NODE_20100118
      #define NODE_20100118
      
      class Tree;
      
      class Node
      {
          Tree * tree_;
          int id_;
      
      public:
      
          Node(Tree * tree, int id);
          ~Node();
          void hi();
      };
      
      #endif /* NODE_20100118 */
      

      Node.cpp:

      #include "Node.h"
      #include "Tree.h"
      
      #include <iostream>
      
      Node::Node(Tree * tree, int id) : tree_(tree), id_(id)
      {
          tree_->incCnt();    // calling a function of Tree
      }
      
      Node::~Node() {
          tree_->decCnt();
      }
      
      void Node::hi() {
          std::cout << "hi (" << id_ << ")" << std::endl;
      }
      

      【讨论】:

        【解决方案3】:

        Tree 的定义需要Node 的定义,但反之则不然,因此您的前向声明是正确的。

        您所要做的就是从Node 类主体中删除需要完整定义Tree 的任何函数的定义,并在.cpp 文件中实现它们,其中两个类的完整定义都在范围内.

        【讨论】:

          【解决方案4】:

          你能把构造函数/析构函数放在 .cxx 文件中吗?您可以在其中包含 Tree.h。

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2011-07-11
            • 1970-01-01
            • 2011-06-16
            • 2015-07-25
            相关资源
            最近更新 更多