我创建了一个名为“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()<<' ';
}
}
答案 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
分配了root
。 treeiterator
有点棘手,因为它必须调用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
命名空间中的所有内容,并将其放在全局命名空间中。这会导致有趣的游戏如reverse
或std::reverse
被调用?通常这会导致疯狂和晦涩的编译器消息,因为糟糕的编译器被混淆为地狱,但有时它不会混淆并在众多中选择最佳选择并默默地打破其他东西。非常有趣的调试。
更多信息:Why is "using namespace std" considered bad practice?
您可以将整个标准库放入您的文件中并剥离其正确的命名空间。这导致潜在的隐藏疼痛的巨大雷区,不值得任何节省时间。由于每个文件和字符输入一些额外的行数,所以产生的错误之一可能会花费更多的清理工作。
没有人想用这个愚蠢的错误来清理代码,所以在专业环境中这样做可能会很昂贵。
答案 1 :(得分:0)
首先,你不应该让root有public
。这是一个严重的OO错误。如果您希望它可用于子类,则应将其设为protected
。