2010-01-18 21 views
8

J'essaie d'implémenter une structure arborescente avec deux classes: Tree et Node. Le problème est que de chaque classe je veux appeler une fonction de l'autre classe, donc de simples déclarations avancées ne suffisent pas. Voyons un exemple:dépendance cyclique entre les fichiers d'en-tête

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

Appel Arbre:

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

Ceci est juste un exemple simple pour illustrer le problème. Donc ce que je veux, c'est appeler une fonction de Tree depuis un objet Node.

Mise à jour # 1: Merci pour les réponses. J'ai essayé de résoudre le problème comme en Java, c'est-à-dire en utilisant un seul fichier par classe. Il semble que je devrais commencer à séparer les fichiers .cpp et .h ...

Mise à jour # 2: Ci-dessous, en suivant les conseils, j'ai collé la solution complète aussi. Merci, problème résolu.

Répondre

5

Dans les en-têtes, déclarer avant les fonctions membres:

class Node 
{ 
    Tree * tree_; 
    int id_; 

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

Dans un fichier .cpp distinct qui comprend tous les en-têtes nécessaires, les définir:

#include "Tree.h" 
#include "Node.h" 

Node::Node(Tree * tree, int id) : tree_(tree), id_(id) 
{ 
    tree_->incCnt(); 
} 

Node::~Node() 
{ 
    tree_->decCnt(); 
} 

etc 

Cela a aussi pour effet de en gardant vos en-têtes lisibles, il est donc facile de voir l'interface d'une classe en un coup d'œil.

0

Pouvez-vous mais le constructeur/destructeur corps dans un fichier .cxx? Vous pourriez inclure Tree.h là.

1

La définition de Tree nécessite la définition de Node mais pas l'inverse, donc votre déclaration forward est correcte.

Tout ce que vous avez à faire est supprimé la définition de toutes les fonctions qui nécessitent une définition complète de Tree du corps de la classe Node et les mettent en œuvre dans un fichier .cpp où des définitions complètes des deux classes sont de portée.

2

En suivant les conseils, voici la solution complète.

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

nœud.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; 
}