Problem:
OP has a circular dependency between minHeapVertex.h and weightedDirectedGraph.h.
Solution:
Eliminate the dependency.
minHeapVertex.h defines minHeapVertex. minHeapVertex requires vertex.
weightedDirectedGraph.h defines vertex and weightedDirectedGraph. Neither require minHeapVertex.
Three possibilities at this point:
Spin vertex off into its own vertex.h header. minHeapVertex.h and weightedDirectedGraph.h both include vertex.h and not each other.
weightedDirectedGraph.h does not require minHeapVertex.h, so remove #include "minHeapVertex.h"
from weightedDirectedGraph.h to break the circle.
forward definition of class vertex;
in minHeapVertex.h and the removal of #include "weightedDirectedGraph.h"
from minHeapVertex.h.
Solution 1 is preferred. Giving vertex its own header may prevent future problems. 2 is easiest to implement. 3 is pretty stupid and not recommended.
Why circular dependency prevented minHeapVertex from seeing vertex:
To make this easier to see, I've removed all of the other includes from the header files.
Here's my idiotic little test.cpp
#include "weightedDirectedGraph.h"
int main(int argc, char * argsv[])
{
return 0;
}
The compiler will make a little temp file of test.cpp. It will then start parsing until it finds an include directive. The included file is copy-pasted into the temp file at the include statement. So the temp file looks sort of like this:
#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;
}
The compiler parses down a little further and sees the include of minHeapVertex.h and copy-pastes so you get this:
#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;
}
That gets parsed down to #include "weightedDirectedGraph.h"
, but fortunately GRAPH
has been defined, so most of weightedDirectedGraph.h gets left out. If it hadn't, Everything in weightedDirectedGraph.h would have been defined again and minHeapVertex.h would once again been included over and over and eventually the compiler would crash or tell you to expletive deleted off with a politely worded error message.
Anyway, we can already see what's gone wrong in the above code trace: minHeapVertex
needs to know type vertex
, but that won't be defined for another 20 lines or so.
If test.cpp had been written as
#include "minHeapVertex.h"
int main(int argc, char * argsv[])
{
return 0;
}
The header files would have been included in the other order and it would have compiled, giving a false sense of security until one day you wrote a program that included weightedDirectedGraph.h first. In other words, the library works until it doesn't, and you didn't change a line of the library's code. Have fun pulling your hair out.
Avoid circular dependencies, circular references and circular saws. All three can rip you up pretty bad.
On to using namespace std;
This evil little shortcut takes EVERYTHING in the std namespace and adds it to the global namespace. If you had a function named reverse, now you have to deal with potential overload conflicts with std::reverse. The standard library is huge. There are a huge number of function, class, and variable names that are just itching to overload, override and just plain trample your stuff.
But that's your problem.
Putting using namespace std;
in a header make it everyone's problem. Anyone who uses your graphing library has to wade through a minefield, and unless they take a close look at your header file and see that declaration they won't have the slightest clue.
Longer discussion can be found here. Either explicitly namespace everything (std::vector, std::string, ...) or pull in only the pieces you need and know will not conflict with your code with using
. Eg:
using std::vector;
using std::string;
Do not put this in your header or someone may wind up wonder why their homebrew vector is freaking out. Probably shouldn't be homebrewing vectors, but you can't save everybody.