如何从派生 class 访问派生基成员?(在 C++ 中)
How can I access derived base member from derived class?(in C++)
基础 class 是 Node
。 AvLNode
是从中派生出来的
在AVLNode
中当this->Left()->Height()
为Balancefactor()
调用时,
Left()
left* from class Node
没有身高被称为。
它以分段错误结束。
基础class:
// A generic tree node class
template<class NodeType>
class Node {
string key;
NodeType* left;
NodeType* right;
NodeType* parent;
public:
Node() { key="-1"; left=NULL; right=NULL; parent = NULL;};
Node(NodeType* source) { //Copy Constructor
key=source->Key();left=source->Left();right=source->Right();parent=source->Parent();
};
void setKey(string aKey) { key = aKey; };
void setLeft(NodeType* aLeft) { left = aLeft; };
void setRight(NodeType* aRight) { right = aRight; };
void setParent(NodeType* aParent) { parent = aParent; };
string Key() { return key; };
NodeType* Left() { return left; };
NodeType* Right() { return right; };
NodeType* Parent() { return parent; };
void copyData(NodeType* source){key=source->key;};
};
派生 class:
class AvlNode : public Node<AvlNode>
{
int height;
public:
AvlNode(){height=1;};
//~AvlNode();
int Height() { return height; };
int BalanceFactor(){
return this->AvlNode::Left()->Height() - this->AvlNode::Right()->Height();
};
int setHeight(int aHeight){height=aHeight;};
};
当您创建 AvlNode
时,其构造函数默认初始化其基础 Node
。所以 left
和 right
指针都是空的。
当然,稍后您可能会使用 setLeft()
或 setRight()
更改它,但不能保证您会这样做。同样在树结构中,你总是有没有左边也没有右边的叶子。并不是所有的节点都有左节点和右节点。
因此,对于可靠的代码,您必须考虑 Left()
或 Right()
为 null 的可能性:
int BalanceFactor()
{
int hl=0, hr=0; // value of height if no child
if (Left())
hl = Left()->Height(); // only dereference the pointer if not null
if (Right())
hr = Right()->Height();
return hl-hr;
};
非常重要的评论与您的问题无关:
您在 github 的评论中提供的代码库包含重要错误:
- 在
addNode()
中,您并不总是 return 一个值:这可能会导致随机节点指针被 returned,从而导致内存损坏。当你递归调用 addNode(...)
你实际上应该 return (addNode(...))
)
Tree::min()
、Tree::max()
和 Tree::findNode()
中的相同错误也适用于递归调用。
- 最后
Tree::Successor()
不会 return 如果 if 条件的 none 为真,即如果 thisKey
为空)。我在这个函数的末尾添加了一个 return thisKey;
。
只有更正了这些错误后,我才能运行 没有段错误的代码。这里是 bst.cpp and avl.cpp 的 运行ning 摘录,我不得不更改一行上的感叹号。
基础 class 是 Node
。 AvLNode
是从中派生出来的
在AVLNode
中当this->Left()->Height()
为Balancefactor()
调用时,
Left()
left* from class Node
没有身高被称为。
它以分段错误结束。
基础class:
// A generic tree node class
template<class NodeType>
class Node {
string key;
NodeType* left;
NodeType* right;
NodeType* parent;
public:
Node() { key="-1"; left=NULL; right=NULL; parent = NULL;};
Node(NodeType* source) { //Copy Constructor
key=source->Key();left=source->Left();right=source->Right();parent=source->Parent();
};
void setKey(string aKey) { key = aKey; };
void setLeft(NodeType* aLeft) { left = aLeft; };
void setRight(NodeType* aRight) { right = aRight; };
void setParent(NodeType* aParent) { parent = aParent; };
string Key() { return key; };
NodeType* Left() { return left; };
NodeType* Right() { return right; };
NodeType* Parent() { return parent; };
void copyData(NodeType* source){key=source->key;};
};
派生 class:
class AvlNode : public Node<AvlNode>
{
int height;
public:
AvlNode(){height=1;};
//~AvlNode();
int Height() { return height; };
int BalanceFactor(){
return this->AvlNode::Left()->Height() - this->AvlNode::Right()->Height();
};
int setHeight(int aHeight){height=aHeight;};
};
当您创建 AvlNode
时,其构造函数默认初始化其基础 Node
。所以 left
和 right
指针都是空的。
当然,稍后您可能会使用 setLeft()
或 setRight()
更改它,但不能保证您会这样做。同样在树结构中,你总是有没有左边也没有右边的叶子。并不是所有的节点都有左节点和右节点。
因此,对于可靠的代码,您必须考虑 Left()
或 Right()
为 null 的可能性:
int BalanceFactor()
{
int hl=0, hr=0; // value of height if no child
if (Left())
hl = Left()->Height(); // only dereference the pointer if not null
if (Right())
hr = Right()->Height();
return hl-hr;
};
非常重要的评论与您的问题无关:
您在 github 的评论中提供的代码库包含重要错误:
- 在
addNode()
中,您并不总是 return 一个值:这可能会导致随机节点指针被 returned,从而导致内存损坏。当你递归调用addNode(...)
你实际上应该return (addNode(...))
) Tree::min()
、Tree::max()
和Tree::findNode()
中的相同错误也适用于递归调用。- 最后
Tree::Successor()
不会 return 如果 if 条件的 none 为真,即如果thisKey
为空)。我在这个函数的末尾添加了一个return thisKey;
。
只有更正了这些错误后,我才能运行 没有段错误的代码。这里是 bst.cpp and avl.cpp 的 运行ning 摘录,我不得不更改一行上的感叹号。