Я пытаюсь реализовать древовидную структуру с двумя классами: 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
от a Node
объект.
Обновление № 1: Спасибо за ответы. Я пытался решить проблему как в Java, т.е. использующий всего один файл в классе. Кажется, что я должен буду начать разделять .cpp и.h файлы...
Обновление № 2: Ниже, после подсказок, я вставил полное решение также. Спасибо, проблема решена.
В заголовках объявите функции-члены вперед:
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
Это также позволяет сохранить ваши заголовки читаемыми, так что легко увидеть интерфейс класса с первого взгляда.
После подсказки вот полное решение.
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;
}
Можете ли вы, но тела конструктора/деструктора в файле .cxx? Вы можете включить туда Tree.h.
В заголовках, вперед объявить функции-члены:
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
Это также позволяет сохранить ваши заголовки читаемыми, так что легко увидеть интерфейс класса.
-121--3383578-Можно ли не использовать тела конструктора/деструктора в файле .cxx? Вы можете включить туда Трея.
-121--3383581- Определение дерева
требует определения узла
, но не других путей, поэтому ваше объявление о пересылке является правильным.
Все, что вам нужно сделать, это удалить определение любых функций, которые требуют полного определения дерева
из тела класса Node
и реализовать их в файле .cpp
, где полные определения обоих классов находятся в области действия.