2010-01-18 13 views
8

Estoy tratando de implementar una estructura de árbol con dos clases: Árbol y Nodo. El problema es que de cada clase quiero llamar a una función de la otra clase, por lo que las declaraciones de reenvío simples no son suficientes. Veamos un ejemplo:dependencia cíclica entre los archivos de encabezado

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

Llamada del árbol:

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

Este es solo un ejemplo simple para ilustrar el problema. Entonces, lo que quiero es llamar a una función de Árbol desde un objeto Nodo.

Actualización n. ° 1: Gracias por las respuestas. Traté de resolver el problema como en Java, es decir, usando solo un archivo por clase. Parece que tendré que empezar a separar archivos .cpp y .h ...

Actualización n. ° 2: A continuación, siguiendo los consejos, pegué la solución completa también. Gracias, problema resuelto.

Respuesta

5

En las cabeceras, declarar adelante las funciones miembro:

class Node 
{ 
    Tree * tree_; 
    int id_; 

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

En un archivo .cpp independiente que incluye todas las cabeceras necesarias, definirlos:

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

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

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

etc 

Esto también tiene el efecto de manteniendo sus encabezados legibles, por lo que es fácil ver la interfaz de una clase de un vistazo.

0

¿Puede usted pero los cuerpos de constructor/destructor en un archivo .cxx? Podría incluir Tree.h allí.

1

La definición de Tree requiere la definición de Node, pero no al revés, por lo que su declaración directa es correcta.

Todo lo que tienes que hacer es eliminado de la definición de las funciones que requieren una definición completa de Tree del cuerpo Node clase e implementan en un archivo .cpp donde las definiciones completas de ambas clases son en su alcance.

2

Siguiendo las sugerencias, aquí está la solución completa.

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

Nodo.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; 
} 
Cuestiones relacionadas