web-dev-qa-db-ja.com

C ++-ネストされたインクルード-回避 'インクルードが深くネストされすぎたエラー'

C++コードで次の接続を使用したい場合、ヘッダーファイルを宣言する最良の方法は何ですか?'includeネストされた深すぎるエラー'を取得しないようにするためです。

Edgeクラスには、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
13
all_by_grace

他の人が示唆しているように、ヘッダーガードを使用します。ただし、問題のクラスを宣言してみてください。また、少なくとも1つのクラスで(値ではなく)ポインターを操作する必要がある場合もありますが、コードを確認しないとわかりません。

したがって、Edge.hは次のようになります。

#ifndef Edge_H
#define Edge_H

class Node;    // forward declaration

Node functionB();

#endif

define関数を別のC++ファイルに入れて、#includes "node.h"にする必要があることに注意してください。

これらすべてが非常に複雑に思える場合は、設計を単純化してみてください。ノードとエッジがお互いを知る必要はおそらくないでしょう—一方向の依存関係で十分です。

そして最後に、二重下線を含む名前はC++で予約されています—独自のコードでそのような名前を作成することは許可されていません。

13
user2100815

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」を前方宣言していることに注意してください。そのため、関数またはメンバー関数が定義されるまでに、返されるクラスも定義されます。

5

インクルードガードの問題は、それらが一致しないことです!

_SOMETHING(1つのアンダースコア)をテストし、見つからない場合は__SOMETHING(2つのアンダースコア)を定義します。これら2つは一致する必要があります。そうでない場合、インクルードガードは機能しません。

他の人が指摘しているように、アンダースコアはライブラリとOS用に予約されているため、アンダースコアで始めることは避けてください。

4
RedX

これは、プラグマガードまたは#pragma once(コンパイラがサポートしている場合は後者)を使用することで防止されます。

プラグマガードを使用するには、次のようにします。

#ifndef SOME_IDENTIFIER
#define SOME_IDENTIFIER

// ... code ...

#endif

すべてのヘッダーファイルのSOME_IDENTIFIERを必ず変更してください。通常、人々はそれをNAME_OF_HEADER_Hにします。片方を変更する場合は、必ず識別子の両方のインスタンスを変更してください。

また、これを行う場合は、行う#includesが内部プラグマガードであることを確認してください。

#pragma onceを使用したいだけで、コンパイラがそれをサポートしている場合は、追加するだけです。

#pragma once

ヘッダーファイルの先頭に。

別の注意点として、関数functionAおよびfunctionBの定義を独自の.cppファイルに移動し、プロトタイプのみを.hファイルに保持して、リンカーエラーが発生しないようにすることを検討してください。

3
Seth Carnegie