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
他の人が示唆しているように、ヘッダーガードを使用します。ただし、問題のクラスを宣言してみてください。また、少なくとも1つのクラスで(値ではなく)ポインターを操作する必要がある場合もありますが、コードを確認しないとわかりません。
したがって、Edge.hは次のようになります。
#ifndef Edge_H
#define Edge_H
class Node; // forward declaration
Node functionB();
#endif
define関数を別のC++ファイルに入れて、#includes "node.h"にする必要があることに注意してください。
これらすべてが非常に複雑に思える場合は、設計を単純化してみてください。ノードとエッジがお互いを知る必要はおそらくないでしょう—一方向の依存関係で十分です。
そして最後に、二重下線を含む名前はC++で予約されています—独自のコードでそのような名前を作成することは許可されていません。
#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 */
#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」を前方宣言していることに注意してください。そのため、関数またはメンバー関数が定義されるまでに、返されるクラスも定義されます。
インクルードガードの問題は、それらが一致しないことです!
_SOMETHING
(1つのアンダースコア)をテストし、見つからない場合は__SOMETHING
(2つのアンダースコア)を定義します。これら2つは一致する必要があります。そうでない場合、インクルードガードは機能しません。
他の人が指摘しているように、アンダースコアはライブラリとOS用に予約されているため、アンダースコアで始めることは避けてください。
これは、プラグマガードまたは#pragma once
(コンパイラがサポートしている場合は後者)を使用することで防止されます。
プラグマガードを使用するには、次のようにします。
#ifndef SOME_IDENTIFIER
#define SOME_IDENTIFIER
// ... code ...
#endif
すべてのヘッダーファイルのSOME_IDENTIFIER
を必ず変更してください。通常、人々はそれをNAME_OF_HEADER_H
にします。片方を変更する場合は、必ず識別子の両方のインスタンスを変更してください。
また、これを行う場合は、行う#include
sが内部プラグマガードであることを確認してください。
#pragma once
を使用したいだけで、コンパイラがそれをサポートしている場合は、追加するだけです。
#pragma once
ヘッダーファイルの先頭に。
別の注意点として、関数functionA
およびfunctionB
の定義を独自の.cppファイルに移動し、プロトタイプのみを.hファイルに保持して、リンカーエラーが発生しないようにすることを検討してください。