9

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

让我们看一个例子:

树.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 */

节点.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();

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

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

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

4

4 回答 4

5

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

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

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

于 2010-01-18T20:46:09.793 回答
2

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

树.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 */

树.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_;
}

节点.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 */

节点.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;
}
于 2010-01-19T15:51:37.723 回答
1

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

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

于 2010-01-18T20:47:49.693 回答
0

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

于 2010-01-18T20:46:40.293 回答