C ++类中的循环依赖

时间:2013-09-22 00:01:48

标签: c++

我对C ++比较陌生,面临循环依赖问题。有人可以帮我解决这个问题吗?

我有两个班级:

class Vertex {
    string name;
    int distance;
    //Vertex path;
    int weight;
    bool known;
    list<Edge> edgeList;
    list<Vertex> adjVertexList;

public:
    Vertex();
    Vertex(string nm);
    virtual ~Vertex();
};

class Edge {
    Vertex target;
    int weight;

public:
    Edge();
    Edge(Vertex v, int w);
    virtual ~Edge();

    Vertex getTarget();
    void setTarget(Vertex target);
    int getWeight();
    void setWeight(int weight);
};

上面的代码给出了以下错误:

  • 'Vertex'未命名类型
  • 'Vertex'尚未宣布
  • 期待')'在'v'
  • 之前

如何解决此问题?

2 个答案:

答案 0 :(得分:6)

您需要的是在Edge中使用Vertex之前向前声明class Edge; class Vertex { string name; int distance; ... }; class Edge { ... }; 类:

Vertex

您不能放置Vertex类型的成员而不是Vertex本身的声明,因为C ++不允许递归类型。在C ++的语义中,这种类型的大小需要是无限的。

当然,您可以在Vertex中指出Vertex

事实上,在class Edge; class Vertex { string name; int distance; int weight; bool known; list<shared_ptr<Edge>> edgeList; list<shared_ptr<Vertex>> adjVertexList; public: Vertex(); Vertex(const string & nm); virtual ~Vertex(); }; class Edge { Vertex target; int weight; public: Edge(); Edge(const Vertex & v, int w); virtual ~Edge(); Vertex getTarget(); void setTarget(const Vertex & target); int getWeight(); void setWeight(int weight); }; 的边缘和邻接列表中,您想要的是指针,而不是对象的副本。因此,您的代码应该像下面那样修复(假设您使用的是C ++ 11,实际上您现在应该使用它):

{{1}}

答案 1 :(得分:2)

如果你考虑一下,实例化一个VertexEdge对象会实例化更多的VertexEdge个对象,因为每个对象都包含一个实例彼此。

要解决此问题,您需要转发声明一个类,该类依赖于您首先使用的类。 前向声明类允许您使用指针和对它们的引用,而不实际使用类,只指向它。

此代码段应该是可编译的,但需要一些额外的内存管理。

class Edge; // This is a forward declaration

class Vertex {
    string name;
    int distance;
    //Vertex path;
    int weight;
    bool known;
    list<Edge*> edgeList;
    list<Vertex*> adjVertexList;

public:
    Vertex();
    Vertex(string nm);
    virtual ~Vertex();
};

class Edge {
    Vertex* target;
    int weight;

public:
    Edge();
    Edge(Vertex* v, int w);
    virtual ~Edge();

    Vertex* getTarget();
    void setTarget(Vertex* target);
    int getWeight();
    void setWeight(int weight);
};

这段代码编译是因为类现在包含指向对象的指针而不是对象本身。

正如BartoszKP建议你应该阅读forward declarations,你可能还需要学习更多关于指针和参考的知识。


由于您仍然遇到问题,我会更详细地更新我的答案。我读到您实际上已经将类拆分为两个头文件,我认为它们是Vertex.hEdge.h。他们应该看起来像这样

<强> Vertex.h

class Edge;
class Vertex
{
    Edge* CreateEdge(); // Declaration of a class function
    // ...
};

<强> Edge.h

class Vertex
class Edge
{
    // ...
};

当您想要使用它来访问其成员或创建实例时,您需要包含Edge的完整定义。基本上,您需要在定义所有类和结构之后放置每个函数的实现。最简单的方法是将函数实现放在各自的.cpp文件中。您似乎想在Edge课程中创建Vertex对象,因此您需要在Vertex的{​​{1}}文件中执行此操作。

<强> Vertex.cpp

.cpp

因为在此#include "Vertex.h" #include "Edge.h" Edge* Vertex::CreateEdge() { return new Edge(); } 文件中完成的第一件事是包含.cppVertex头文件,它们具有各自的类定义,所以您可以完全使用EdgeVertex课程。

您需要在如何组织声明和定义方面有一定的顺序,如下所示

Edge