I need a little guidance, I have created two header files which contain definitions of of a class in each. The header 'Connection.h' contains a class, 'Connection' which has an instance of the other class 'Node' which is within the 'Node.h', and vice versa. Needless to say I have included the 'Node.h' in the connection header and 'Connection.h' in the node header.
Now I have missing type specifiers, how can I resolve this?
typedef would work, although from what you're describing (and not being able to see the code) I am supposing that maybe one of your classes should be integrated into the other.
Is there any way that you can re-organize your code so that one class does not depend on the other? Otherwise, even if it was all in one file you'd have problems:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
//If you declare ClassB here, you'd have ClassA undefined.
class ClassA
{
ClassB TheClass; // ClassB isn't defined yet
};
class ClassB
{
ClassA TheClass;
};
int main()
{
ClassA Hello;
return 0;
}
I tried embedding the Node class into Connection class, but I got an error stating that I could not use an 'incompleted' variable type..such an implementation would look like:
#ifndef DATE_H
#define DATE_H
class Connection
{
public:
float cost;
Node fromNode; // an instance of node which is not created yet..
Node toNode;
class Node
{
public:
int nodeId;
Connection connection; // an instance of connection
float costSoFar;
};
};
#endif
I told you, typedef would work, but I am suggesting not that you embed your code, but rather that you combine your code. Based on the code you've shown, it looks like you just need to create a doubly linked list.
Apologies, but I have been looking at the implementation for 'typedef', i dont know how to use it to help, are you suggesting that it van be used like a method prototype ( defining a method at the top of the cpp file )
It's similar to a method prototype, but it's defining a non-standard type. Using it in your code, though, would be pretty ugly. Like I said before, using a doubly linked list would work very well.
I dont understand how a doubly linked list is a solution to my problem, Im not working with those sort of 'nodes'. It could just be a highlight of my ignorance that I cant see the solution.
It appears that the point of the classes is to be able to iterate from one node to the next, and to be able to reference the previous node (first link) and the next node (second link). Each node, aside from the links, also contain data in the form of the cost of that particular node, and the sum of the costs of all previous nodes including itself. While this would be a daunting task to undertake with two separate classes on it's own, it also appears that the only other thing you're doing is attempting to traverse the list.
There are a few approaches that can help in this situation. First, you only need to have a "complete variable type" if you are actually using the type. References and pointers to the type do not have to be complete and can operate on a forward declared type. Also, splitting each class into a header and source file can also help split the definitions, assuming that only the implementation of each needs to use the other.
I think there was a nice article on include files that also covered this somewhere on here. I'll try to find it.
I am developing a path finding algorithm. Connections 'Connect' two nodes, and obviously nodes are between the connections. I am implementing a form of the 'Dikstra' algorithm.
Without getting into exactly what I'm developing, it's irrelevant, I wanted to know how the two data types - node and connection - can contain an instance of one and other. I appreciate that your trying your best to help. My code takes the form it does to accommodate the needs of my algorithm.
#ifndef DATE_H
#define DATE_H
class Node
{
public:
int nodeId;
Connection connection; // An instance of a, not yet defined, class
float costSoFar;
};
class Connection
{
public:
float cost;
Node fromNode; // an instance of the previously defined class 'Node'
Node toNode;
};
#endif
If you really have to, then moorecm is right. Build your classes with references to each other. You can even build a subclass with a reference to a superclass if you need to.
thanks for the link moorecm, i thought i had it nailed, but similar problems persist. I once again have two separate header files:
Node.h
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
#ifndef __NODE_H_INCLUDED__ // guarded
#define __NODE_H_INCLUDED__
#include "connection.h" // need to include this
class Connection; // forward declaration
class Node
{
public:
int nodeId;
Connection connection; // an instance of connection
float costSoFar;
};
#endif
Connection.h
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
#ifndef __CONNECTION_H_INCLUDED__ // guarded
#define __CONNECTION_H_INCLUDED__
#include "node.h" // need to include this
class Node; // forward declaration
class Connection
{
public:
float cost;
Node fromNode; // instance of a node
Node toNode; // another instance of a node
};
#endif
I then include both headers in my main.cpp, but the later of the two i include always brings up the same errors about the type not existing, and C++ does not support default int etc..
You're still trying to build it by creating a complete version of the class. You can't do that, because the class hasn't been created yet. You must use references.
I think I have it now, but now when i try to create an instance of node within my main.cpp, i get an error stating that 'there is no appropriate default constructor available':
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
#ifndef __CONNECTION_H_INCLUDED__ // guarded
#define __CONNECTION_H_INCLUDED__
#include "node.h" // need this
class Node; // forward declaration
class Connection
{
private:
float cost;
Node& fromNode; // reference to node
Node& toNode; // another reference to node
};
#endif
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
#ifndef __NODE_H_INCLUDED__ // guarded
#define __NODE_H_INCLUDED__
#include "connection.h" // need this
class Connection; // forward declaration
class Node
{
public:
int nodeId;
Connection connection; // instance of connection
float costSoFar;
};
#endif
You have to include a ctor initializer for the references, so that your references can be initialized when you create an object.
I would hesitate to do what you're doing, though, because upon looking at this, I'm thinking you may create a memory overload through circular programming.
Have you implemented either class in a .cpp file? If you have just Declared the class there is nothing you can do to compile the fact that you have included both headers in each other and you are still getting type doesn't exists is because there is no type defined. Stub out the .cpps and compile.
After reading your first post again "I have two header files", yeah if you dont have an implementation you have no type.
I am developing a path finding algorithm. Connections 'Connect' two nodes, and obviously nodes are between the connections. I am implementing a form of the 'Dikstra' algorithm.
I think your description is a bit simplistic, but after looking up the algorithm it looks to me like every node needs a list of connections, and every connection 'connects' exactly 2 nodes.
I would suggest beginning with
in Node.h:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
#include <list>
class Connection ;
class Node
{
std::list<Connection*> connections ;
public:
void connect(Connection* c)
{
connections.push_back(c) ;
}
};
#include "node.h"
class Connection
{
// connections don't make sense without existing nodes,
// so references seem appropriate. You could also use
// Node objects here, I suppose, but it doesn't make
// sense to me. connections don't 'have' nodes.
Node& from ;
Node& to ;
public:
Connection( Node& f, Node& t /*, other stuff?*/ )
: from(f), to(t)
{
from.connect(this);
to.connect(this) ;
}
};