I have been struggling with errors when trying to build a binary tree using a queue. The problem is what classes should include what files and how to reference objects from the other classes? I threw my files into an IDE in an attempt to pinpoint just what the problems are and the results are below. Currently my issue is that in the Queue.h file, treePtr "does not name a type". You can see the evolution of this problem here This question is different from other posts because the two classes are friend classes. This brings up the problem of circular dependencies. I have tried all sorts of combinations of including files and forward declaring but one combination causes one type of issue, and another creates different errors.
Here is the main class:
#include <cstdlib>
#include "Tree.cpp"
using namespace std;
int main() {
Tree tree;
tree.addTreeNode(5);
return 0;
}
Here is the Queue.h:
#ifndef QUEUE_H_
#define QUEUE_H_
class Tree; //Was instructed to put this here
class Queue {
friend class Tree;
private:
typedef struct node {
Tree::treePtr treeNode; //Here is the problem
node* next;
}* nodePtr;
nodePtr head;
nodePtr current;
public:
Queue();
virtual ~Queue();
void push(Tree::treePtr t); //Here is the problem
int pop();
void print();
};
#endif /* QUEUE_H_ */
This is Tree.h:
#ifndef TREE_H_
#define TREE_H_
#include "Queue.h" //Was instructed to put this here
class Tree {
friend class Queue;
private:
Queue q; //Edit: Most likely problem since Queue and Tree are friends
typedef struct tree {
int data;
tree* left;
tree* right;
}* treePtr;
treePtr root;
int numNodes;
public:
Tree();
virtual ~Tree();
void addTreeNode(int integer);
};
#endif /* TREE_H_ */
This is tree.cpp
#include <cstdlib>
#include <iostream>
#include "Tree.h"
using namespace std;
Tree::Tree() {
root = NULL;
numNodes = 0;
}
void Tree::addTreeNode(int integer) {
numNodes++;
treePtr t = new tree;
t->left = NULL;
t->right = NULL;
t->data = integer;
cout << "add root\n";
root = t;
q.push(t); //This is a problem
q.print();
}
Tree::~Tree() {
// TODO Auto-generated destructor stub
}
You have to compile Tree.cpp
and (I suppose you have one) Queue.cpp
separately, instead of including Tree.cpp
in your main.cpp
.
Forward declarations are fine for friending classes, even if you do so circular.
Put #include "Tree.h"
in your Queue.cpp
file, to let the compiler see the full declaration.
In main.cpp
just put #include " Tree.h"
.
To get the final executable link all of the produced object files main.o(bj)
, Tree.o(bj)
and Queue.o(bj)
.
See also [Why should I not include cpp files and instead use a header?] please.
As I've noticed now your actual problem is, you cannot access nested classes/structs from a forward declared class/struct as you're requiring with accessing treePtr
from Queue
(treePtr
should be better named something like TreeNode
or similar BTW).
You cannot make treePtr
a private nested type in this case, it must be publicly visible.
A viable way is to put treePtr
in a namespace internal_
, that indicates it's not intended for usage outside the API.
Another viable way is to make Queue
a template class, that accepts any type of tree
or other kind of nodes. Since can't see any use case, why Queue
needs to know about the internal specifications of tree
(besides the trivial stuff like copying aso.), it's not really necessary to make Queue
a friend
class.