试图在另一个头文件中使用一个头文件中的类
Trying to use a class in one header file in another header file
我有一个weightedDirectedGraph
类和一个vertex
类在他们自己的头文件,weightedDirectedGraph.h。
#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.h中的vertex
类有关。谁能告诉我我哪里做错了?一直在它几个小时,尝试向前声明顶点类,尝试删除一些包括",查找错误代码和改变的东西,但没有工作,只是以一堆错误结束。
问题:
OP在minHeapVertex.h和weightedDirectedGraph.h之间有一个循环依赖。
<标题>解决方案:消除依赖。
minHeapVertex.h定义minHeapVertex。minHeapVertex需要顶点
weightedDirectedGraph.h定义了顶点和加权directedgraph。都不需要minHeapVertex
目前有三种可能:
旋转顶点到自己的顶点。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是相当愚蠢的,不推荐。
为什么循环依赖阻止minHeapVertex看到顶点:
为了更容易看到,我从头文件中删除了所有其他包含。
这是我愚蠢的小测试。
#include "weightedDirectedGraph.h"
int main(int argc, char * argsv[])
{
return 0;
}
编译器将生成一个test.cpp的小临时文件。然后,它将开始解析,直到找到一个包含指令。包含的文件在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被省略了。如果没有,那么weightedDirectedGraph.h中的所有内容都将被重新定义,minHeapVertex.h将再次被一遍又一遍地包含,最终编译器将崩溃或告诉您删除并给出礼貌的错误消息。
无论如何,我们已经可以在上面的代码跟踪中看到哪里出了问题:minHeapVertex
需要知道类型vertex
,但在另外20行左右的代码中不会定义。
如果test.cpp被写成
#include "minHeapVertex.h"
int main(int argc, char * argsv[])
{
return 0;
}
头文件将以另一种顺序包含,它将被编译,给人一种错误的安全感,直到有一天您编写的程序首先包含了weightedDirectedGraph.h。换句话说,库可以正常工作,直到它不能工作为止,并且您没有更改库的任何代码。祝你玩得开心。
避免循环依赖、循环引用和循环锯。这三个都能把你撕成碎片。
On to using namespace std;
这个邪恶的小快捷方式将std命名空间中的所有内容添加到全局命名空间中。如果有一个名为reverse的函数,现在必须处理与std::reverse的潜在重载冲突。标准库是巨大的。有大量的函数、类和变量名都想重载、覆盖和践踏你的东西。
但那是你的问题。
将using namespace std;
放在标题中使它成为每个人的问题。任何使用你的绘图库的人都必须穿过雷区,除非他们仔细查看你的头文件并看到那个声明,否则他们不会有丝毫的线索。
可以在这里找到更详细的讨论。要么显式地命名所有内容(std::vector, std::string,…),要么只拉入您需要并且知道的部分,这些部分不会与using
的代码冲突。如:
using std::vector;
using std::string;
不要把这个放在你的标题中,否则有人可能会想知道为什么他们的自制向量会崩溃。也许不应该是自制载体,但你不能拯救所有人。
标题>- 为什么两个不同的未命名名称空间可以共存于一个cpp文件中
- 挂起和取消挂起一个文件DLL
- C++-试图将函数指针推回到另一个CPP文件中的矢量时出错
- 输入到文件并输出到另一个文件,并将流文件传递给函数
- C++试图读取一个文件并输出到另一个文本文件
- 如何从另一个文件继承私有成员变量和公共函数
- 在 Windows 上,是否可以让 dll 在不使用 PATH 环境变量的情况下在另一个文件夹中查找依赖项?
- 如何打开并写入一个名称取自C++中字符串的文件
- 构建一个由C和C++文件组成的库
- c++多进程编写一个唯一的文件
- 如何使用CLion在Mac上创建一个新的.txt文件
- 如何将class.cpp和class.hpp编译为一个.o文件
- 写入文件会产生一个空文件或根本没有文件
- 如何将不同的可执行文件合并到一个窗口框架中进行编码?像浏览器一样
- 生成一个生成文件,该生成文件使用Automake在一个步骤中编译和链接所有源文件
- 为什么我的 heap.h 文件给我一个LNK2001错误?
- Pantheios 不使用 MFC 应用程序写入一个文件(一个 exe + 两个 DLL)
- 在C++中一次读取一个文件一个int
- 输入/输出文件(一个字母的大写)
- 如何使用两个预编译的头文件.一个用于托管代码,另一个用于非托管代码.xxx.PCH不是一个有效的预编译头文件