9

と の 2 つのクラスでツリーのような構造を実装しようとしていTreeますNode。問題は、各クラスから他のクラスの関数を呼び出したいため、単純な前方宣言では不十分なことです。

例を見てみましょう:

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();

これは、問題を説明するための単純な例です。だから私が欲しいのは、オブジェクトTreeから関数を呼び出すことです。Node

更新 #1:回答ありがとうございます。Java のように問題を解決しようとしました。つまり、クラスごとに 1 つのファイルのみを使用しました。.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

ヒントに従って、ここに完全な解決策があります。

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

ツリー.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 */

ノード.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 に答える