基类和派生类

时间:2016-04-17 16:36:57

标签: c++ inheritance

我正在实施自己的BST和AVL树。

BSTree继承了Dictionary类。字典类是抽象的,即只提供在继承Dictionary的类中实现的纯虚函数。现在,我实现了类BSTree并在类AVL中继承它。这两个类都有root作为私有成员。 BSTree工作得很好。但是AVL中的功能是"行为不端"。

这是Dictionary.hpp:

#ifndef DICTIONARY_HPP_
#define DICTIONARY_HPP_
template<class Key, class Value>
class Dictionary
{
public:
    virtual ~Dictionary(){};
    virtual void put(const Key& key, const Value& value) = 0;
};
#endif

这是BSTree.hpp:

 #ifndef BSTREE_HPP
 #define BSTREE_HPP
 #include "Dictionary.hpp"

 namespace ntl{

 template<class Key,class Value>
 class Node{
     public:
         Key key;
         Value value;
         int height;
         Node *left;
         Node *right;
         Node *parent;
         Node();
 };

 template<class Key,class Value>
 Node<Key,Value>::Node(){
     key=defaultData(key);
     value=defaultData(value);
     height=0;
     left=right=parent=NULL;
 }

template <class Key, class Value>
class BSTree : public Dictionary<Key, Value> {
private:
    Node<Key,Value> *root;
    int n;
public:
    BSTree();
    bool has(const Key& key);
    void put(const Key& key, const Value& value);
};

template<class Key,class Value>
BSTree<Key,Value>::BSTree(){
    root=NULL;
    n=0;
}

template<class Key,class Value>
bool BSTree<Key,Value>::has(const Key& key){
    //return true if key is present
    //return false if key isn't present
}

emplate<class Key, class Value>
void BSTree<Key,Value>:: put(const Key& key, const Value& value){
    Node<Key,Value> * y=NULL;
    Node<Key,Value> * x=this->root;
    while(x!=NULL){
        y=x;
        if(key<x->key){
            x=x->left;
        }else if(key>x->key){
            x=x->right;
        }else{
            break;
        }
    }
    if(x!=NULL){
        x->value=value;
    }else{
        Node<Key,Value> *newNode=new Node<Key,Value>(key,value);
        newNode->height=0;
        newNode->parent=y;
        if(y==NULL){
            root=newNode;
        }else if(newNode->key<y->key){
            y->left=newNode;
        }else{
            y->right=newNode;
        }
        n++;
        int lh,rh;
        while(newNode!=NULL){
            if(newNode->left==NULL)
                lh=-1;
            else
                lh=newNode->left->height;
            if(newNode->right==NULL)
                rh=-1;
            else
                rh=newNode->right->height;
            if(lh>rh)
                newNode->height=1+lh;
            else
                newNode->height=1+rh;
            newNode=newNode->parent;
        }
    }
}

这是AVL.hpp:

#ifndef AVL_HPP
#define AVL_HPP
#include "BSTree.hpp"

namespace ntl{

template <class Key,class Value>
class AVL : public BSTree<Key, Value> {
  private:
      Node<Key,Value> *root;
      int n;
  public:
      AVL();
      virtual void put(const Key& key, const Value& value);
};

template<class Key,class Value>
void AVL<Key,Value>::put(const Key& key, const Value& value){
  std::cout<<"Put function of AVL called\n";
  if(this->root==NULL){
    std::cout<<"Root is NULL\n";
    BSTree<Key,Value>::put(key,value);
  }else if(this->has(key)){
    BSTree<Key,Value>::put(key,value);
  }else{
    //Some More Stuff
  }
}
#endif

在main.cpp中我做了类似的事情:

ntl::AVL<int,int> t;
t.put(50,1);
t.put(30,2);
t.put(10,3);

我得到了输出:

  

将AVL的功能称为

     

Root为NULL

     

将AVL的功能称为

     

Root为NULL

     

将AVL的功能称为

     

Root为NULL

为什么root始终为NULL。正确插入数字(我使用自定义打印功能打印它们)。我想工作总是在BSTree的根变量上完成。怎么避免呢? 请帮助。

1 个答案:

答案 0 :(得分:3)

问题

模板类AVL有自己的私有根:

    class AVL : public BSTree<Key, Value> {
    private:
         Node<Key,Value> *root;
    ...

模板类BSTree也是如此:

    class BSTree : public Dictionary<Key, Value> {
    private:
        Node<Key,Value> *root;
    ...

虽然您似乎在BSTree::root中正确更新了BSTree::put(),但AVL::root是另一个成员变量,它不受这些插入使用其基类&#39; BSTree::put()

    ...  
    if(this->root==NULL){
        std::cout<<"Root is NULL\n";
        BSTree<Key,Value>::put(key,value);  // if this succeeds, BSTRee's root will be non null
    ...                                     // but AVL's root is unchanged 

解决方案:

摆脱AVL的根,因为显然它不是必需的。

你可以选择:

  • 使BSTree的root受到保护,以便AVL可以访问它。
  • 或在BSTree中创建受保护(或公共)的getter,以便AVL可以获得root的值而无法更改它。