17

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

4 に答える 4

13

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

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

#ifndef EDGE_H
#define EDGE_H

class Node;    // forward declaration

Node functionB();

#endif

関数を別のC++ファイルで定義する必要があることに注意してください。このファイルには、「node.h」が含まれています。

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

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

于 2011-05-16T18:35:31.453 に答える
5

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

于 2011-05-16T18:50:00.613 に答える
5

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

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

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

于 2011-05-16T18:56:48.047 に答える
3

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

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

#ifndef SOME_IDENTIFIER
#define SOME_IDENTIFIER

// ... code ...

#endif

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

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

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

#pragma once

ヘッダーファイルの先頭に移動します。

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

于 2011-05-16T18:32:49.863 に答える