17

如果我想在我的 C++ 代码中有以下连接,那么声明头文件的最佳方法是什么,以免出现“包含嵌套太深的错误”

在我的边缘类上,我有一些需要返回 Node 对象的函数。Edge 类也是如此,我有需要返回 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

边缘.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

正如其他人所建议的那样,使用标头保护。但也尝试向前声明有问题的类。您可能还必须在至少一个类中使用指针(而不是值),但如果没有看到代码,我们无法判断。

所以 edge.h 应该像这样:

#ifndef EDGE_H
#define EDGE_H

class Node;    // forward declaration

Node functionB();

#endif

请注意,您必须在单独的 C++ 文件中定义您的函数,然后#includes "node.h"。

如果这一切看起来很复杂,那么您应该尝试简化您的设计。节点和边可能没有必要相互了解——单向依赖就足够了。

最后,包含双下划线的名称在 C++ 中是保留的——你不能在自己的代码中创建这样的名称。

于 2011-05-16T18:35:31.453 回答
5

边缘.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 */

节点.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

您的包含警卫的问题是它们不匹配!

你测试_SOMETHING(一个下划线),然后如果没有找到你定义__SOMETHING(两个下划线);这两个应该匹配,否则包含防护不起作用!

正如其他人所指出的那样,避免使用下划线开头,因为它们是为库和操作系统保留的。

于 2011-05-16T18:56:48.047 回答
3

这可以通过使用编译指示守卫或#pragma once(如果您的编译器支持后者)来防止。

要使用编译指示守卫,只需执行以下操作:

#ifndef SOME_IDENTIFIER
#define SOME_IDENTIFIER

// ... code ...

#endif

确保更改SOME_IDENTIFIER每个头文件。通常人们会做到NAME_OF_HEADER_H;如果更改一个,请确保更改标识符的两个实例。

此外,如果您这样做,请确保#include您所做的任何 s 都pragma 守卫内。

如果您只想使用#pragma once并且您的编译器支持它,则只需添加

#pragma once

到头文件的顶部。

另一方面,考虑将函数的定义移动functionAfunctionB它们自己的 .cpp 文件中,并将原型仅保留在 .h 文件中,这样就不会出现链接器错误。

于 2011-05-16T18:32:49.863 回答