2

I want to build a tree using level order traversal. When I declare my Queue object in the private scope, I get the error "field 'q' has incomplete type 'Queue'. My program works if I declare a Queue in the addTreeNode(int integer) function, but when I move it to the header file, I get the new error. From what I have read it seems that the Tree class does not know how much memory to allocate to the Queue object. How to I fix this?

EDIT: For anyone browsing this question, the problem has nothing to do with inclusions files etc. The problem here is that Tree has an instance of a Queue, while Queue and Tree are friend classes, meaning they have access to each other's data members. This forces a situation that is circular and wonks out c++. The solution to my problem was to make Queue a template class.

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 Header:

#pragma once
#include "tree.h"

class Queue {

    friend class Tree;

    private:
        typedef struct node {
            Tree::treePtr treeNode;
            node* next;
        }* nodePtr;

        nodePtr head;
        nodePtr current;

    public:  //This is where the functions go
        Queue();
        void push(Tree::treePtr t);
        int pop();
        void print();

};

This is Tree.h:

#pragma once


class Queue;

class Tree{

    friend class Queue;

    private:

        Queue q;

        typedef struct tree {
            int data;
            tree* left;
            tree* right;
        }* treePtr;

        treePtr root;
        int numNodes;


    public:

        Tree();
        void addTreeNode(int integer);

};

This is tree.cpp

#include <cstdlib>
#include <iostream>

#include "Tree.h"
#include "Queue.cpp"


using namespace std;

Tree::Tree() {
    root = NULL;
}

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);  
    q.print();

}
lefunction
  • 301
  • 2
  • 16
  • Unfortunately, forward declaring only works with pointers and references. And functions. – Weak to Enuma Elish Nov 11 '15 at 15:09
  • For anyone browsing this question, the problem has nothing to do with inclusions files etc. So clicking on the duplicate answer above will not help you if your problem is the same as mine. The problem here is that Tree has an instance of a Queue, while Queue and Tree are friend classes, meaning they have access to each other's data members. This forces a situation that is circular and wonks out c++. The solution to my problem was to make Queue a template class. – lefunction Nov 12 '15 at 20:50

1 Answers1

2

To instantiate your queue upon creation of the Tree, the compiler needs to know what the Queue class looks like when reading Tree.h. So you need to add

#include "Queue.h"

to Tree.h which will make the full Queue declaration visible to the compiler before it starts reading Tree.

CompuChip
  • 9,143
  • 4
  • 24
  • 48
  • I tried this but this introduces all kinds of errors. I #include "Queue.cpp" in my "tree.cpp" and everything works fine if I declare the Queue in tree.cpp – lefunction Nov 11 '15 at 15:13
  • You _never_ (well, _almost_ never) `#include` .cpp files, just header files. – CompuChip Nov 11 '15 at 15:15
  • I added the other .h and .cpp files from my program. If I try to include Queue.h file in Tree.h, like I said, there are lots of error. I tried to change which files include what, but that does not seem to work here. – lefunction Nov 11 '15 at 15:32
  • You have a circular reference now: Queue.h includes Tree.h and Tree.h includes Queue.h. One of them should be a forward declaration (`class Tree;` in Queue.h) and the other one should be an include. – CompuChip Nov 11 '15 at 15:40
  • When I do what you say, Queue.h does not recognize the type of the treePtr in the struct node* – lefunction Nov 11 '15 at 16:06
  • It seems to me that no matter what I do here, there is a problem because these classes are friends. Is it possible that I can't declare stuff from one, when the other declares stuff from the first? Maybe instead I should make my tree a child class to a queue? Maybe from a design perspective that make more sense since it doesn't work for both to have data members from the others? – lefunction Nov 11 '15 at 16:47
  • The problem is your Tree depends on the full Queue class, and Queue uses an internal class of Tree, hence they both need to see the full header and you have a circular reference. I haven't looked at your code in detail, but I suspect that separating `Tree::treePtr` into a new class or making `Queue::node::treenode` into a pointer will fix your issue. – CompuChip Nov 12 '15 at 08:33
  • Hey, thanks for following up. The solution was to make Queue a template class, so it could accept any object. Then there was no need for Queue to have access to the data members of Tree. Funny thing though, because it turned out that the template class wouldn't link unless I did some gymnastics. SO I chose to put Queue header and Tree header, separately, in the same file, and Queue class and Tree class in the same file separately, which basically defeats the purpose of separating classes, but oh well, I actually like the design, c++ is a finicky language though – lefunction Nov 12 '15 at 20:41