C ++ - Вложенное включение - Избегать «слишком глубоко вложенных ошибок» - PullRequest
11 голосов
/ 16 мая 2011

Каков наилучший способ объявить мои заголовочные файлы, если я хочу, чтобы в моем коде C ++ были следующие соединения, просто чтобы я не получил 'включенную вложенную слишком глубоко ошибку' ?

В моем пограничном классе у меня есть некоторые функции, которые должны возвращать объект Node. То же самое для класса Edge, у меня есть функции, которые должны возвращать объект Node. Однако компилятор не позволяет мне иметь эту вещь вложенного цикла.

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

Ответы [ 4 ]

11 голосов
/ 16 мая 2011

Как и предлагали другие, используйте защиту заголовков. Но также попробуйте объявить рассматриваемые классы. Возможно, вам также придется работать с указателями (а не со значениями) хотя бы в одном из ваших классов, но, не видя код, мы не можем сказать.

Таким образом, файл edge.h должен выглядеть примерно так:

#ifndef EDGE_H
#define EDGE_H

class Node;    // forward declaration

Node functionB();

#endif

Обратите внимание, что вам придется определить вашу функцию в отдельном файле C ++, который затем #include "node.h".

Если все это кажется очень сложным, попробуйте упростить свой дизайн. Вероятно, узлам и ребрам не обязательно знать друг о друге - достаточно односторонней зависимости.

И, наконец, имена, содержащие двойные подчеркивания, зарезервированы в C ++ - вам не разрешено создавать такие имена в вашем собственном коде.

4 голосов
/ 16 мая 2011

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

Обратите внимание, что я заранее объявил классы 'Edge' и 'Node' до включения другого заголовка, так что к тому времени, когда функция или функция-член определены, класс, который она возвращает, также определен.

3 голосов
/ 16 мая 2011

Проблема с вашими включенными охранниками состоит в том, что они не совпадают!

Вы проверяете на _SOMETHING (одно подчеркивание), а затем, если не найдено, вы определяете __SOMETHING (два подчеркивания);эти два должны совпадать, в противном случае включаемая защита не работает!

Как уже отмечали другие, избегайте начинать с подчеркиваний, поскольку они зарезервированы для библиотек и ОС.

3 голосов
/ 16 мая 2011

Этого можно избежать, используя либо прагма-охранники, либо #pragma once (последний, если ваш компилятор поддерживает это).

Чтобы использовать прагма-охранники, просто сделайте следующее:

#ifndef SOME_IDENTIFIER
#define SOME_IDENTIFIER

// ... code ...

#endif

MakeОбязательно измените SOME_IDENTIFIER для каждого заголовочного файла.Обычно люди делают это NAME_OF_HEADER_H;убедитесь, что вы изменили оба экземпляра идентификатора, если вы изменили его.

Также, если вы сделаете это, убедитесь, что все #include s, которые вы делаете, являются внутри защитников прагмы.

Если вы просто хотите использовать #pragma once и ваш компилятор поддерживает его, вам просто нужно добавить

#pragma once

в начало вашего заголовочного файла.

В другой заметке,рассмотрите возможность перемещения определения функций functionA и functionB в их собственные файлы .cpp и сохраните только прототип в файлах .h, чтобы избежать ошибок компоновщика.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...