-1

I have made a superclass named "tree". I have constructed the tree in this class. Now, I want to pass the root of the constructed tree to another class which is a subclass of tree. But when I try to pass it, the subclass calls the supercalss constructor and sets it to NULL;

struct node
{
    struct node *left;
    struct node *right;
    int val;
};
struct node *create(int val)
{
    struct node *temp = (struct node *)malloc(sizeof(struct node));
    temp->val = val;
    temp->left = temp->right = NULL;
    return temp;
};
class tree
{
    public:
        struct node *root;
        tree()
        {
            root = NULL;

        }
        void createtree()
        {
            root = create(5);
        }
        void preorder()
        {
            preorderp(root);
        }
        void preorderp(struct node *p)
        {
            if(!p) {
                return;
            }
            cout<<p->val<<' ';
            preorderp(p->left);
            preorderp(p->right);
        }
};

This is the definition of my tree class. It just creates a tree with one node having value 5. Now I want to pass the new root created to a subclass of tree.

class treeiterator:public tree
{
    struct node *p;
    stack<struct node *> s;
    public:
        treeiterator()
        {   
            p = root;
            push(root);
        }
        bool hasnext();
        int next();
    private:
        void push(struct node *root);
};

I create an object for tree first and then do createtree. Now, when I create an object for treeiterator, it's member p gets sets to NULL since supercalss constructor is also called. How can I just access the tree created in the superclass in subclass? Full code:

#include <bits/stdc++.h>
using namespace std;
struct node
{
    struct node *left;
    struct node *right;
    int val;
};
struct node *create(int val)
{
    struct node *temp = (struct node *)malloc(sizeof(struct node));
    temp->val = val;
    temp->left = temp->right = NULL;
    return temp;
};
class tree
{
    public:
        struct node *root;
        tree()
        {
            root = NULL;

        }
        void createtree()
        {
            root = create(5);
        }
        void preorder()
        {
            preorderp(root);
        }
        void preorderp(struct node *p)
        {
            if(!p) {
                return;
            }
            cout<<p->val<<' ';
            preorderp(p->left);
            preorderp(p->right);
        }


};
class treeiterator:public tree
{
    struct node *p;
    stack<struct node *> s;
    public:
        treeiterator()
        {
            p = root;
            push(root);
        }
        bool hasnext();
        int next();
    private:
        void push(struct node *root);
};
void treeiterator::push(struct node *t)
{
    while(t) {
        s.push(t);
        t = t->left;
    }
}
bool treeiterator::hasnext()
{
    return s.empty()?1:0;
}
int treeiterator::next()
{
    struct node *t = s.top();
    int val = t->val;
    s.pop();
    if(t->right) {
        push(t->right);
    }
    return val;
}
int main()
{
    tree t;
    t.createtree();
    t.preorder();
    treeiterator it;
    while(it.hasnext()) {
        cout<<it.next()<<' ';
    }
}
Shivam Mitra
  • 1,040
  • 3
  • 17
  • 33
  • 1
    Why are you using `malloc()` instead of `new` in C++? – MikeCAT Jun 07 '16 at 15:13
  • There should be no need to. `root` is public, Wait a sec. On reread I think I see it. When you create a `treeiterator` it comes with a `tree` built in. No need to build a `tree`. You would need to call `createtree` on the `treeiterator`, but I [recommend reading up on RAII](http://en.cppreference.com/w/cpp/language/raii) and performing the initialization in the constructor. – user4581301 Jun 07 '16 at 15:14
  • @user4581301 :can you explain it in detail? – Shivam Mitra Jun 07 '16 at 15:18
  • 1
    You seems to be messing instances and class inheritance. Each instance of `tree` or `treeiterator` in your code will have its own `root`. You should post a full compiling example to clarify your saying. – Johan Jun 07 '16 at 15:19
  • @Johan : included full code. – Shivam Mitra Jun 07 '16 at 15:29

2 Answers2

1

Because of inheritance every treeiterator is also a tree. This means

treeiterator treeIt;
treeIt.createtree();

will do what OP wants. There is no need to make a separate tree and moving the root around.

However this is a bit odd in the world of C++ because OP is under-using the constructor. For example, node could be:

struct node
{
    node *left;
    node *right;
    int val;

    node(int inval): 
        val(inval), 
        left(nullptr), 
        right(nullptr)
        // the above is a Member Initializer List. It makes sure all of your 
        // members are initialized before the body of the constructor runs.
    {
    }
};

That bit after the : in the constructor is the Member Initializer List. Now when you allocate a node it's initialized and ready to be linked. For tree

class tree
{
    public:
        struct node *root; // almost certainly should not be public.
                           // also should be a std::unique_ptr<node>
        tree(int inval)
        {
            root = new node(5); // note new in place of malloc. new allocates 
                                // storage and calls constructors. malloc should 
                                // only be used in C++ in rare edge-cases.
        }
        /* obsolete
        void createtree()
        {
            root = create(5);
        }
        */
        ...
};

tree is assigned a root on allocation. treeiterator is a wee bit trickier because it must call tree's constructor to set up root.

class treeiterator:public tree
{
    struct node *p; // Don't see the point off this
    stack<struct node *> s; // or this, but that's another question
    public:
        treeiterator(int inval): 
            tree(inval) // call's tree's constructor
        {   
        }
        bool hasnext();
        int next();
    private:
        void push(struct node *root);
};

Allocating a treeiterator now guarantees that it is all ready to go with no further work.

treeiterator treeIt(5); // all done.

All of the above is covered within the first few chapters of any good C++ programming text. I recommend getting one and reading it, because right now it looks like you are trying to write bad C.

Off topic 1:

You are going to quickly find that this code is in violation of the Rule Of Three. What is The Rule of Three? If you don't know, read the link. It will save you much time and hair-pulling

Off Topic 2:

#include <bits/stdc++.h>
using namespace std;

Is a ticking time bomb. The first line includes the entire standard library, but only in GCC. Your code is now doing far, far more work than it need to to compile, is no longer standard C++, and is not portable to other compilers and may well break with the next revision of GCC. Don't use anything in bits. It internal compiler-specific stuff with no guarantees what-so-ever.

More here: Why should I not #include <bits/stdc++.h>?

The second line takes everything in the std namespace and places it in the global namespace. This leads to fun games like is reverse or std::reverse being called? Often this leads to insane and arcane compiler messages because the poor compiler is confused as hell, but sometimes it's not confused and picks the best choice among the many and silently breaks something else. Great fun debugging.

More here: Why is "using namespace std" considered bad practice?

Together you have the entire standard library pulled into your file AND stripped of it's proper namespace. This results in a vast minefield of potential hidden pain that is not worth any perceived time savings. One of the resulting bugs could cost more clean up than years of typing a few extra lines per file and characters.

No one want to clean up code with this stupid a mistake, so doing this in a professional setting can be costly.

Community
  • 1
  • 1
user4581301
  • 33,082
  • 7
  • 33
  • 54
0

First, you should not have root has public. This is a gross OO error. If you want it to be available to subclasses you should make it protected.

asam
  • 359
  • 3
  • 12