我在自己的头文件RICHDirectedGraph.h中有一个weightedDirectedGraph
类和一个vertex
类。就是这样:
#ifndef GRAPH
#define GRAPH
#include <iostream>
#include <string>
#include <vector>
#include <list>
#include "minHeapVertex.h"
using namespace std;
class vertex
{
public:
string data;
list<vertex *> neighbors;
bool known;
int distance, id;
vertex * path;
vertex(string x)
{
data = x;
}
};
class weightedDirectedGraph
{
private:
list<vertex *> vertexList;
vector<vector<int> > edgeWeights; //2D vector to store edge weights
int idCount;
weightedDirectedGraph()
{
idCount = 0;
}
vertex * findVertex(string s);
void dijkstrasAlg(vertex * s);
public:
void addVertex(string x);
//adds bi-directional edges
void addWeightedEdge(string x, string y, int weight);
};
#endif
我在minHeapVertex.h文件中有一个minHeapVertex
类,它将用作Dijkstra算法中的优先级队列。这是文件:
#ifndef MIN_HEAP_VERTEX
#define MIN_HEAP_VERTEX
#include <iostream>
#include <vector>
#include "weightedDirectedGraph.h"
using namespace std;
class minHeapVertex
{
public:
explicit minHeapVertex(int capacity = 100)
:heapArray(capacity + 1), currentSize{ 0 } {}
bool isEmpty() const
{
return (currentSize == 0);
}
vertex * getMinVertex() const; //getting C2143 error here that says I'm missing a semi-colon before '*'. Doesn't make sense though.
void insert(vertex * insertItem);
void deleteMin();
vertex * deleteAndReturnMin();
void makeEmpty()
{
currentSize = 0;
}
void decreaseKey(int index, int decreaseValue);
void remove(int index);
private:
void buildHeap();
void percolateDown(int hole);
vector<vertex *> heapArray;
int currentSize;
};
#endif
我得到了很多编译错误(第一个是getMinVertex()声明中的C2143错误)我认为它可能与尝试访问minHeapVertex中的vertex
类有关。 h。有人可以告诉我我做错了什么吗?试了几个小时,试着向前声明顶点类,尝试删除一些包含“”,查找错误代码并改变了一些东西,但没有任何工作只是结束了一堆错误。
答案 0 :(得分:2)
OP在minHeapVertex.h和weightedDirectedGraph.h之间存在循环依赖。
消除依赖性。
minHeapVertex.h定义了minHeapVertex。 minHeapVertex需要顶点。
weightedDirectedGraph.h定义了vertex和weightedDirectedGraph。既不需要minHeapVertex。
此时有三种可能性:
将顶点旋转到自己的vertex.h标头中。 minHeapVertex.h和weightedDirectedGraph.h都包含vertex.h而不是彼此。
weightedDirectedGraph.h不需要minHeapVertex.h,因此从weightedDirectedGraph.h中删除#include "minHeapVertex.h"
以打破圆圈。
在minHeapVertex.h中定义class vertex;
并从minHeapVertex.h中删除#include "weightedDirectedGraph.h"
。
溶液1是优选的。为顶点提供自己的标头可以防止将来出现问题。 2最容易实现。 3非常愚蠢,不推荐。
为了便于查看,我已从头文件中删除了所有其他包含。
这是我的愚蠢小test.cpp
#include "weightedDirectedGraph.h"
int main(int argc, char * argsv[])
{
return 0;
}
编译器会生成一个test.cpp的临时文件。然后它将开始解析,直到找到include指令。将包含的文件复制粘贴到include语句的临时文件中。所以临时文件看起来像这样:
#define GRAPH
#include "minHeapVertex.h"
using namespace std;
class vertex
{
public:
string data;
list<vertex *> neighbors;
bool known;
int distance, id;
vertex * path;
vertex(string x)
{
data = x;
}
};
class weightedDirectedGraph
{
private:
list<vertex *> vertexList;
vector<vector<int> > edgeWeights; //2D vector to store edge weights
int idCount;
weightedDirectedGraph()
{
idCount = 0;
}
vertex * findVertex(string s);
void dijkstrasAlg(vertex * s);
public:
void addVertex(string x);
//adds bi-directional edges
void addWeightedEdge(string x, string y, int weight);
};
int main(int argc, char * argsv[])
{
return 0;
}
编译器进一步解析并查看minHeapVertex.h和copy-paste的包含,以便得到这个:
#define GRAPH
#define MIN_HEAP_VERTEX
#include "weightedDirectedGraph.h"
using namespace std;
class minHeapVertex
{
public:
explicit minHeapVertex(int capacity = 100)
:heapArray(capacity + 1), currentSize{ 0 } {}
bool isEmpty() const
{
return (currentSize == 0);
}
vertex * getMinVertex() const; //getting C2143 error here that says I'm missing a semi-colon before '*'. Doesn't make sense though.
void insert(vertex * insertItem);
void deleteMin();
vertex * deleteAndReturnMin();
void makeEmpty()
{
currentSize = 0;
}
void decreaseKey(int index, int decreaseValue);
void remove(int index);
private:
void buildHeap();
void percolateDown(int hole);
vector<vertex *> heapArray;
int currentSize;
};
using namespace std;
class vertex
{
public:
string data;
list<vertex *> neighbors;
bool known;
int distance, id;
vertex * path;
vertex(string x)
{
data = x;
}
};
class weightedDirectedGraph
{
private:
list<vertex *> vertexList;
vector<vector<int> > edgeWeights; //2D vector to store edge weights
int idCount;
weightedDirectedGraph()
{
idCount = 0;
}
vertex * findVertex(string s);
void dijkstrasAlg(vertex * s);
public:
void addVertex(string x);
//adds bi-directional edges
void addWeightedEdge(string x, string y, int weight);
};
int main(int argc, char * argsv[])
{
return 0;
}
将其解析为#include "weightedDirectedGraph.h"
,但幸运的是GRAPH
已定义,因此大多数weightedDirectedGraph.h都被遗漏了。如果还没有,那么RICHDirectedGraph.h中的所有东西都会被再次定义,并且minHeapVertex.h会再次被一次又一次地包含在内,最终编译器会崩溃或者告诉你 expletive deleted off礼貌的措辞错误信息。
无论如何,我们已经可以看到上面的代码跟踪出了什么问题:minHeapVertex
需要知道类型vertex
,但是不会为另外20行左右定义。
如果test.cpp已写为
#include "minHeapVertex.h"
int main(int argc, char * argsv[])
{
return 0;
}
头文件将被包含在另一个订单中并且它将被编译,给出一种错误的安全感,直到有一天你编写了一个首先包含weightedDirectedGraph.h的程序。换句话说,库可以工作,直到它没有,并且您没有更改库代码的一行。把头发拉出来玩得很开心。
避免循环依赖,循环引用和圆锯。这三个人都可以把你扯得很糟糕。
On using namespace std;
这个邪恶的小捷径在std命名空间中占用一切,并将其添加到全局命名空间。如果你有一个名为reverse的函数,那么现在你必须处理与std :: reverse的潜在重载冲突。标准库很庞大。有大量的函数,类和变量名称只是需要重载,覆盖并且只是简单地践踏你的东西。
但那是你的问题。
将using namespace std;
放入标题会使每个人都遇到问题。任何使用你的图形库的人都必须趟过一个雷区,除非他们仔细查看你的头文件并看到这个声明,否则他们就不会有任何线索。
Longer discussion can be found here.显式命名所有内容(std :: vector,std :: string,...)或仅提取您需要的部分,并且知道不会与using
的代码冲突。例如:
using std::vector;
using std::string;
不要把它放在你的标题中,或者有人可能会想知道为什么他们的自制矢量吓坏了。可能不应该是自制的载体,但你无法拯救每个人。