C ++ - Incluir anidado - Evitar 'incluir error anidado demasiado profundo'

¿Cuál es la mejor manera de declarar mis archivos de encabezado si quiero tener las siguientes conexiones en mi código C ++, solo para no obtener el 'incluir error anidado demasiado profundo'?

En mi clase de borde, tengo algunas funciones que necesitan devolver un objeto Node. Lo mismo para la clase Edge, tengo funciones que necesitan devolver un objeto Node. Sin embargo, el compilador no me permite tener este bucle anidado.

Node.h

#ifndef _NODE_h__
#define __NODE_h__

#include "Edge.h" 
public:
    Node();
    ~Node();
    void setName(string);
    string getName();
    void addEdge(Edge*);
    vector<Edge* > getEdges() { return _edges; };
};
#endif

Edge.h

#ifndef _EDGE_h__
#define __EDGE_h__

#include "Node.h"
class Edge 
{
public:

    Edge();
    Edge(bool);
    ~Edge();
    bool hasBeenSeen() { return _seen; };
    void reset() { _seen = false; };  // resets seen param to false
    Node* getSource() { return _source; };
    Node* getTarget() { return _target; };
    void setSource(Node* source) { _source = source; };
    void setTarget(Node* target) { _target = target; };
};
#endif

preguntado el 16 de mayo de 11 a las 18:05

Por un lado, necesita protectores de encabezado: stackoverflow.com/questions/2979384/purpose-of-header-guards -

Intenté usar la macro IFNDEF y DEFINE, pero aún obtengo el 'error de inclusión anidado demasiado profundo'. -

@all_by_grace: Entonces sospecho que no lo hiciste bien. Pero también tendrás problemas con la dependencia circular. -

No use nombres con __ en ellos; están reservados para que los utilice la implementación. -

Solo quería señalarle que en realidad está usando guardias pero con un pequeño error: la macro definida en el #ifndef declaración debe ser la misma que en el #definehecho. -

4 Respuestas

Como han sugerido otros, use protectores de encabezado. Pero también trate de declarar las clases en cuestión. Es posible que también tenga que trabajar con punteros (en lugar de valores) en al menos una de sus clases, pero sin ver el código, no podemos decirlo.

Así que edge.h debería gustarle algo como:

#ifndef EDGE_H
#define EDGE_H

class Node;    // forward declaration

Node functionB();

#endif

Tenga en cuenta que tendrá que definir su función en un archivo C ++ separado que luego #incluye "node.h".

Si todo esto parece muy complicado, entonces debería intentar simplificar su diseño. Probablemente no sea necesario que los nodos y los bordes se conozcan entre sí; una dependencia unidireccional debería ser suficiente.

Y, por último, los nombres que contienen guiones bajos dobles están reservados en C ++; no puede crear dichos nombres en su propio código.

Respondido el 02 de junio de 15 a las 17:06

Edge.h

#ifndef EDGE_H_INCLUDED
#define EDGE_H_INCLUDED

class Node;

class Edge
{
    int edge_num;
public:
    Edge(int i) : edge_num(i) { };
    Node memberB();
};

#include "Node.h"  

Node Edge::memberB() { Node n(edge_num); return n; }
Node functionB()     { Node n(2);        return n; }

#endif /* EDGE_H_INCLUDED */

Node.h

#ifndef NODE_H_INCLUDED
#define NODE_H_INCLUDED

class Edge;

class Node
{
    int node_num;
public:
    Node(int i) : node_num(i) { };
    Edge memberA();
};

#include "Edge.h"

Edge Node::memberA() { Edge e(node_num); return e; }
Edge functionA()     { Edge e(1);        return e; }

#endif /* NODE_H_INCLUDED */

Tenga en cuenta que he declarado hacia adelante las clases 'Edge' y 'Node' antes de que se incluya el otro encabezado, de modo que cuando se define la función o la función miembro, la clase que devuelve también está definida.

contestado el 16 de mayo de 11 a las 23:05

¡El problema con tus protectores de inclusión es que no coinciden!

Pruebas para _SOMETHING (un guión bajo) y luego, si no lo encuentra, defina __SOMETHING (dos guiones bajos); estos dos deben coincidir, de lo contrario, el protector de inclusión no funciona.

Como otros han señalado, evite comenzar las cosas con guiones bajos, ya que están reservados para bibliotecas y sistemas operativos.

Respondido 22 Jul 16, 09:07

He arreglado el código en la pregunta, pero en el momento en que se escribió esto, la observación era completamente correcta. El comentario de doble subrayado todavía se aplica; los nombres que comienzan con subrayado y una letra mayúscula también están reservados. - Jonathan Leffler

@Jonathan En mi humilde opinión, nunca se debe corregir el código en la página de preguntas, ya que eso podría generar confusión en parte del póster y en parte de las personas que responden preguntas. Si eso se hubiera "arreglado" desde el principio, nadie podría detectar este error. - RedX

No estoy de acuerdo conmigo mismo de hace cinco años; He revertido mi edición. - Jonathan Leffler

Esto se evita mediante el uso de protectores de pragma o #pragma once (este último si su compilador lo admite).

Para usar protectores de pragma, simplemente haga esto:

#ifndef SOME_IDENTIFIER
#define SOME_IDENTIFIER

// ... code ...

#endif

Asegúrate de cambiar SOME_IDENTIFIER para cada archivo de encabezado. Por lo general, la gente lo hace NAME_OF_HEADER_H; asegúrese de cambiar ambas instancias del identificador si cambia una.

Además, si hace esto, asegúrese de que #includes lo haces eres dentro los guardias del pragma.

Si solo quieres usar #pragma once y su compilador lo admite, solo tiene que agregar

#pragma once

en la parte superior de su archivo de encabezado.

En otra nota, considere mover la definición de las funciones functionA y functionB a sus propios archivos .cpp y manteniendo solo el prototipo en los archivos .h, para que no obtenga errores del vinculador.

contestado el 16 de mayo de 11 a las 22:05

No creo que incluir guardias ayude con referencias circulares. Si se refiere a miembros de tipo puntero, funcionará, pero por otra razón. - csl

No es la respuesta que estás buscando? Examinar otras preguntas etiquetadas or haz tu propia pregunta.