如何在c ++中将值从超类传递给子类

时间:2016-06-07 15:12:34

标签: c++ inheritance tree

我创建了一个名为“tree”的超类。我已经在这个类中构建了树。现在,我想将构造树的根传递给另一个类,它是树的子类。但是当我尝试传递它时,子类调用supercalss构造函数并将其设置为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);
        }
};

这是我的树类的定义。它只是创建一个树,其中一个节点的值为5.现在我想将创建的新根传递给树的子类。

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);
};

我首先为树创建一个对象,然后创建createtree。现在,当我为treeiterator创建一个对象时,它的成员p将sets设置为NULL,因为还调用了supercalss构造函数。我怎样才能访问子类中超类中创建的树? 完整代码:

#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()<<' ';
    }
}

2 个答案:

答案 0 :(得分:1)

由于继承,每个treeiterator也是tree。这意味着

treeiterator treeIt;
treeIt.createtree();

会做OP想要的。无需单独tree并移动root

然而,在C ++世界中这有点奇怪,因为OP使用的是构造函数。例如,node可以是:

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.
    {
    }
};

构造函数中:之后的那一位是Member Initializer List。 现在,当您分配node时,它已初始化并准备好进行链接。对于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分配了roottreeiterator有点棘手,因为它必须调用tree的构造函数来设置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);
};

分配treeiterator现在可以确保它已准备就绪,无需进一步的工作。

treeiterator treeIt(5); // all done.

the first few chapters of any good C++ programming text涵盖了以上所有内容。我建议找一个并阅读它,因为现在看起来你正在尝试写坏C.

偏离主题1:

您将很快发现此代码违反了规则三。 What is The Rule of Three?如果您不知道,请阅读链接。它会为你节省很多时间和吸引力

关闭主题2:

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

是定时炸弹。第一行包括整个标准库,但仅限于GCC。您的代码现在做的远远超过编译所需的工作,不再是标准的C ++,并且不能移植到其他编译器,并且很可能会破坏GCC的下一个版本。不要在bits中使用任何内容。它是内部编译器特定的东西,不能保证永远。

更多信息:Why should I not #include <bits/stdc++.h>?

第二行接受std命名空间中的所有内容,并将其放在全局命名空间中。这会导致有趣的游戏如reversestd::reverse被调用?通常这会导致疯狂和晦涩的编译器消息,因为糟糕的编译器被混淆为地狱,但有时它不会混淆并在众多中选择最佳选择并默默地打破其他东西。非常有趣的调试。

更多信息:Why is "using namespace std" considered bad practice?

您可以将整个标准库放入您的文件中并剥离其正确的命名空间。这导致潜在的隐藏疼痛的巨大雷区,不值得任何节省时间。由于每个文件和字符输入一些额外的行数,所以产生的错误之一可能会花费更多的清理工作。

没有人想用这个愚蠢的错误来清理代码,所以在专业环境中这样做可能会很昂贵。

答案 1 :(得分:0)

首先,你不应该让root有public。这是一个严重的OO错误。如果您希望它可用于子类,则应将其设为protected