Reputation: 67
I have created a graph.h, graph.cpp, and main.cpp In my graphics.h I've created two private structures an Edge and a Node, and I've declared Edge first above Node but an Edge has a node member so I've forward declared the Node struct but I'm running into issues saying a "Graph::Node*" is incompatible with "Node *" this occurs in my graph.cpp AddEdgeByName(string,string,double) function, why does this happen? On top of this I dont know why I had to declare in (graphics.cpp) the function Graph::Node * Graph::findByName(string name) like that I thought the way i originally tried to declare it like this Node * Graph::findByName(string name) would work but it gave me an error. Im trying to make a Directed weighted graph by the way.
#include <iostream>
#include <string>
#include <vector>
using std::cout;
using std::cin;
using std::endl;
using std::string;
using std::vector;
struct Node;
class Graph{
private:
typedef struct edge{
double edgeWeight;
Node *pointsTo;
edge(){}
edge(const edge & copyObject){
this->edgeWeight = copyObject.edgeWeight;
this->pointsTo = copyObject.pointsTo;
}
} Edge;
typedef struct node{
string name;
vector<Edge> myEdges;// list of outgoing edges for this node
node(string myName){
name = myName;
}
node(const node & copyObject){
this->name = copyObject.name;
this->myEdges = copyObject.myEdges;
}
// adds another edge to this node
void addEdge(Node *pointTo, double weight){
Edge newEdge;
newEdge.edgeWeight = weight;
newEdge.pointsTo =
newEdge.pointsTo = pointTo;
myEdges.push_back(newEdge);
}
} Node;
vector<Node*> graph; // vector containing all the nodes for the
//graph
public:
Graph();
// finds a node in the list of nodes for the graph, using the name
Node * findByName(string name);
void add(string name);
void addEdgeByName(string first, string second,double weight);
};
#endif
// this is graphics.cpp
#include "Graph.h"
Graph::Graph(){
}
Graph::Node * Graph::findByName(string name){
for(std::vector<Node*>::iterator it = graph.begin(); it != graph.end(); ++it){
if((*it)->name == name){
return *it;
}
}
return NULL;
}
void Graph::add(string name){
Node * newNode = new Node(name); // creates a new node with the given //name
graph.push_back(newNode); // adds this node to our list of nodes in the //graph
}
// this publicly accessible function adds edges to each of the strings
void Graph::addEdgeByName(string first, string second,double weight){
Node * firstNode = findByName(first);
Node * secondNode = findByName(second);
firstNode->addEdge(secondNode,weight);
secondNode->addEdge(firstNode,weight);
}
Upvotes: 0
Views: 2463
Reputation: 141574
Regarding the public/private problem: You can't. Having the structure with private
visibility means it is only usable within your code's functions.
Making it public
would be one solution. Another option would be to not use nested classes at all. (Personally I don't like them).
You should avoid doing typedef struct edge {....} Edge;
. Instead use struct Edge { .... };
. It gains nothing to give your struct two names.
Your forward declaration struct Node;
declares a different struct to Graph::Node
. Perhaps you meant for struct Node;
to be inside the Graph
definition. Then it would be a forward declaration of Graph::Node
.
Finally, Graph::
is required in Graph::Node * Graph::findByName(string name)
because the compiler reads from left to right, so if it sees Node *
then it doesn't know what you are talking about yet. This problem can be avoided by using C++11 return type syntax:
auto Graph::findByName(string name) -> Node *
where the names in the ->
part are looked up in the Graph
scope, since the compiler has already seen that we are implementing a Graph
member function.
Upvotes: 1
Reputation: 9609
Don't use typedef struct node { … } Node
in C++. That's C.
Node
is a structure inside Graph
so you need to forward-declare it there, not outside it:
class Graph {
private:
struct Node;
struct Edge {
…
};
struct Node {
…
};
};
Upvotes: 0