user3743168
user3743168

Reputation: 67

when defining a private structure in a class how do i use it as a function parameter or return type?

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

Answers (2)

M.M
M.M

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

StenSoft
StenSoft

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

Related Questions