在 C++ 多级继承方面需要帮助

时间:2021-02-04 18:38:59

标签: c++ templates inheritance polymorphism c++17

我正在尝试为树及其节点构建多级继承。所以我从一个BaseNode开始,然后我创建一个从BaseNode继承的BSTNode,然后我创建一个从BSTNode继承的AVLNode。这些类中的每一个都有需要重载的成员函数,但它们需要返回各自的类。因此,如果我调用 AVLNode-> 来 insert(1) 那么这应该返回一个 AVLNode 类型的指针,而 BSTNode->insert(1) 应该返回一个 BSTNode 类型的指针。而且,这些节点中的每一个都可以存储多种类型作为键,例如,我们可以有一个键为 int 类型的 BSTNode,还有另一个键为 long 类型的 BSTNode。这些节点将成为代表各自树的另一组类的一部分。

class BaseNode {
    T key;
    BaseNode<T>* insert();
}
class BSTNode: public BaseNode {
    BSTNode<T>* insert(); // extending the BaseNode insert
}
class AVLNode: public BSTNode {
   AVLNode<T>* insert(); // extending the BSTNode insert
}

class BST {
    BSTNode<T>* root;
}

class AVL {
    AVLNode<T> *root;
}

我曾尝试查看 CRTP,但它仅适用于 1 级继承。我需要一些关于如何解决这个问题或是否可以使用 C++ 解决的指针(双关语)。

这是我的代码:

template<typename T>
class AbstractBinaryTreeNode {
    protected:
        T key;
        int counter;
        AbstractBinaryTreeNode<T> *left, *right, *parent;
    public:
        virtual void inorder_print();
        virtual void pre_order_print();
        virtual void post_order_print();
        virtual void print_key();

        virtual T get_key();
        virtual void set_key(T key);

        virtual AbstractBinaryTreeNode<T>* get_parent();
        virtual AbstractBinaryTreeNode<T>* get_left();
        virtual AbstractBinaryTreeNode<T>* get_right();
        virtual void set_parent(AbstractBinaryTreeNode<T>* node);
        virtual void set_left(AbstractBinaryTreeNode<T>* node);
        virtual void set_right(AbstractBinaryTreeNode<T>* node);

        virtual bool check_ri();
        virtual AbstractBinaryTreeNode* search(T key);
        virtual AbstractBinaryTreeNode* insert(T key);
        virtual AbstractBinaryTreeNode* remove();

        virtual ~AbstractBinaryTreeNode() {};
};

template<typename T>
class BinaryTreeNode: public AbstractBinaryTreeNode<T> {
    public:
        void inorder_print() ;
        void pre_order_print() ;
        void post_order_print() ;
        void print_key() ;
        T get_key() ;
        void set_key(T key) ;
        BinaryTreeNode<T>* get_parent() ;
        BinaryTreeNode<T>* get_left() ;
        BinaryTreeNode<T>* get_right() ;
        void set_parent(BinaryTreeNode<T>* node);
        void set_left(BinaryTreeNode<T>* node);
        void set_right(BinaryTreeNode<T>* node);
};

class BSTNode: public BinaryTreeNode<T> {
    public:
        BSTNode(T key);
        
        bool check_ri() ;
        BSTNode<T>* insert(T key);
        BSTNode<T>* search(T key);
        BSTNode<T>* remove();
        BSTNode<T>* next_larger();
        BSTNode<T>* find_min();
};

我得到的错误是:

error: invalid conversion from ‘BinaryTreeNode<int>*’ to ‘BSTNode<int>*’

编辑:经过思考,我研究了接口实现分离,但现在重载不起作用。

binary_tree_node.hpp

#pragma once

#include"Impl/binary_tree_node_impl.hpp"

template<typename T>
class BinaryTreeNode{
    public:
        BinaryTreeNodeImpl<T, BinaryTreeNode<T>>* impl;
        BinaryTreeNode();
        BinaryTreeNode(T key);

        virtual void inorder_print();
        virtual void pre_order_print();
        virtual void post_order_print();
        void print_key() ;
        virtual T get_key() ;
        void set_key(T key);

        BinaryTreeNode<T>* get_parent();
        BinaryTreeNode<T>* get_left();
        BinaryTreeNode<T>* get_right();
        
        virtual void set_parent(void* node);
        virtual void set_left(void* node);
        virtual void set_right(void* node);

        virtual bool check_ri() = 0;
};

#include"binary_tree_node.tpp"

binary_tree_node.tpp

模板

BinaryTreeNode<T>::BinaryTreeNode() {
    this->impl = new BinaryTreeNodeImpl<T, BinaryTreeNode<T>>();
}

template<typename T>
BinaryTreeNode<T>::BinaryTreeNode(T key) {
    this->impl = new BinaryTreeNodeImpl<T, BinaryTreeNode<T>>(this);
}

template<typename T>
BinaryTreeNode<T>* BinaryTreeNode<T>::get_parent() {
    return this->impl->get_parent();
}

template<typename T>
BinaryTreeNode<T>* BinaryTreeNode<T>::get_left() {
    return this->impl->get_left();
}

template<typename T>
BinaryTreeNode<T>* BinaryTreeNode<T>::get_right() {
    return this->impl->get_right();
}

template<typename T>
void BinaryTreeNode<T>::set_parent(void* node) {
    this->impl->set_parent((BinaryTreeNode<T>*) node);
}

template<typename T>
void BinaryTreeNode<T>::set_left(void* node) {
    this->impl->set_left((BinaryTreeNode<T>*)node);
}

template<typename T>
void BinaryTreeNode<T>::set_right(void* node) {
    this->impl->set_right((BinaryTreeNode<T>*)node);
}

template<typename T>
void BinaryTreeNode<T>::print_key() {
    this->impl->print_key();
}

template<typename T>
void BinaryTreeNode<T>::pre_order_print() {
    this->impl->pre_order_print();
}

template<typename T>
void BinaryTreeNode<T>::inorder_print() {
    this->impl->inorder_print();
}

template<typename T>
void BinaryTreeNode<T>::post_order_print() {
    this->impl->post_order_print();
}

template<typename T>
T BinaryTreeNode<T>::get_key() {
    return this->impl->get_key();
}

template<typename T>
void BinaryTreeNode<T>::set_key(T key) {
    this->impl->set_key(key);
}

binary_tree_impl.hpp

#pragma once

template<typename T, class NodeType>
class BinaryTreeImpl {
    public:
        NodeType *root;

        BinaryTreeImpl() {};
        BinaryTreeImpl(T key) {};
        
        virtual void inorder_print();
        virtual void pre_order_print();
        virtual void post_order_print();

        virtual bool check_ri() = 0;
        virtual NodeType* insert(T key) = 0;
        virtual NodeType* remove(T key) = 0;
        virtual NodeType* search(T key) = 0;
};

#include"binary_tree_impl.tpp"

binary_tree_impl.tpp

template<typename T, class NodeType>
void BinaryTreeImpl<T, NodeType>::inorder_print() {
    if(this->root) 
        this->root->inorder_print();
}

template<typename T, class NodeType>
void BinaryTreeImpl<T, NodeType>::pre_order_print() {
    if (this->root)
        this->root->pre_order_print();
}

template<typename T, class NodeType>
void BinaryTreeImpl<T, NodeType>::post_order_print() {
    if(this->root) 
        this->root->post_order_print();
}

binary_tree_node_impl.hpp

# pragma once


template<typename T, class NodeType>
class BinaryTreeNodeImpl {
    public:
        T key;
        int counter;
        NodeType *node;
        NodeType *left, *right, *parent; 
    
        BinaryTreeNodeImpl() {};
        BinaryTreeNodeImpl(T key, NodeType* node);

        virtual bool check_ri() {};
        virtual void inorder_print();
        virtual void pre_order_print();
        virtual void post_order_print();
        
        T get_key();
        void set_key(T key);
        void print_key();

        virtual NodeType* get_parent();
        virtual NodeType* get_left();
        virtual NodeType* get_right();

        virtual void set_parent(void* node);
        virtual void set_left(void* node);
        virtual void set_right(void* node);
};

#include "binary_tree_node_impl.tpp"

binary_tree_node_impl.tpp

模板<

typename T, class NodeType>
BinaryTreeNodeImpl<T, NodeType>::BinaryTreeNodeImpl(T key, NodeType* node) {
    this->key = key;
    this->node = node; 
}

template<typename T, class NodeType>
NodeType* BinaryTreeNodeImpl<T, NodeType>::get_parent() {
    return this->parent;
}

template<typename T, class NodeType>
NodeType* BinaryTreeNodeImpl<T, NodeType>::get_left() {
    return this->left;
}

template<typename T, class NodeType>
NodeType* BinaryTreeNodeImpl<T, NodeType>::get_right() {
    return this->right;
}

template<typename T, class NodeType>
void BinaryTreeNodeImpl<T, NodeType>::set_parent(void* node) {
    this->parent = (NodeType*)node;
}

template<typename T, class NodeType>
void BinaryTreeNodeImpl<T, NodeType>::set_left(void* node) {
    this->left = (NodeType*)node;
}

template<typename T, class NodeType>
void BinaryTreeNodeImpl<T, NodeType>::set_right(void* node) {
    this->right = (NodeType*)node;
}

template<typename T, class NodeType>
void BinaryTreeNodeImpl<T, NodeType>::print_key() {
    std::cout<<this->key<<std::endl;
}

template<typename T, class NodeType>
void BinaryTreeNodeImpl<T, NodeType>::pre_order_print() {
    for(int i = 0; i < this->counter; i++)
        std::cout<<this->key<<" ";
    if (this->left)
        this->left->pre_order_print();
    if(this->right)
        this->right->pre_order_print();
}

template<typename T, class NodeType>
void BinaryTreeNodeImpl<T, NodeType>::inorder_print() {
    if (this->left)
        this->left->inorder_print();
    for(int i = 0; i < this->counter; i++)
        std::cout<<this->key<<" ";
    if(this->right)
        this->right->inorder_print();
}

template<typename T, class NodeType>
void BinaryTreeNodeImpl<T, NodeType>::post_order_print() {
    if (this->left)
        this->left->pre_order_print();
    if(this->right)
        this->right->pre_order_print();
    for(int i = 0; i < this->counter; i++)
        std::cout<<this->key<<" ";
}

template<typename T, class NodeType>
T BinaryTreeNodeImpl<T, NodeType>::get_key() {
    return this->key;
}

template<typename T, class NodeType>
void BinaryTreeNodeImpl<T, NodeType>::set_key(T key) {
    this->key = key;
}

binary_tree.hpp

#pragma once 

#include"binary_tree_node.hpp"
#include"Impl/binary_tree_impl.hpp"

template<typename T>
class BinaryTree {
    public:
        BinaryTreeImpl<T, BSTNode<T>> *impl;
        BinaryTree() {};
        BinaryTree(T key);
        virtual void inorder_print();
        virtual void pre_order_print();
        virtual void post_order_print();

        virtual bool check_ri() = 0;
        virtual BinaryTreeNode<T>* insert(T key) = 0;
        virtual BinaryTreeNode<T>* remove(T key) = 0;
        virtual BinaryTreeNode<T>* search(T key) = 0;
};

#include"binary_tree.tpp"

binary_tree.tpp

template<typename T>
void BinaryTree<T>::inorder_print() {
    this->impl->inorder_print();
}

template<typename T>
void BinaryTree<T>::pre_order_print() {
    this->impl->pre_order_print();
}

template<typename T>
void BinaryTree<T>::post_order_print() {
    this->impl->post_order_print();
}

bst_impl.hpp

#pragma once

#include"../../binary_tree/Impl/binary_tree_impl.hpp"

template<typename T, class NodeType>
class BSTImpl: public BinaryTreeImpl<T, NodeType> {
    private:
        NodeType *root;     
    public:
        BSTImpl() {};
        BSTImpl(T key);

        bool check_ri();
        NodeType* insert(T key) override;
        NodeType* search(T key) override;
        NodeType* remove(T key) override;

        ~BSTImpl();
};

#include"bst_impl.tpp"

bst_impl.tpp

template<typename T, class NodeType>
BSTImpl<T, NodeType>::BSTImpl(T key) {
    if (this->root == nullptr)
        this->root = new NodeType(key);
    else
        this->root->insert(key);
}

template<typename T, class NodeType>
NodeType* BSTImpl<T, NodeType>::insert(T key) {
    if (this->root == nullptr)
        this->root = new NodeType(key);
    else
        this->root->insert(key);
}

template<typename T, class NodeType>
bool BSTImpl<T, NodeType>::check_ri() {
    if (this->root) {
        return this->root->check_ri();
    } else {
        return true;
    }
}

template<typename T, class NodeType>
NodeType* BSTImpl<T, NodeType>::search(T key) {
    if (this->root)
        return this->root->search(key);
    else
        return nullptr;
}

template<typename T, class NodeType>
NodeType* BSTImpl<T, NodeType>::remove(T key) {
    if(this->root){
        NodeType *temp = this->root->search(key);
        if (temp == nullptr)
            return nullptr;
        else if (temp == this->root) {
            NodeType *node = new NodeType(0);
            node->set_left(this->root);
            this->root->set_parent(node);
            NodeType* deleted = this->root->remove();
            this->root = node->get_left();
            if(this->root) 
                this->root->set_parent(nullptr);
            return deleted;
        } else {
            NodeType *deleted = temp->remove();
            this->check_ri();
            return deleted;
        }
    }
}

bst_node_impl.hpp

#pragma once

#include"../../binary_tree/Impl/binary_tree_node_impl.hpp"

template<typename T, class NodeType>
class BSTNodeImpl: public BinaryTreeNodeImpl<T, NodeType> {
    public:
        T key;
        int counter;
        NodeType *node;
        NodeType *left, *right, *parent;

        BSTNodeImpl(T key, NodeType* node);
        bool check_ri();
        T get_key();

        NodeType* insert(T key);
        NodeType* search(T key);
        NodeType* remove();
        NodeType* next_larger();
        NodeType* find_min();
};

#include"bst_node_impl.tpp"

bst_node_impl.tpp

template<typename T, class NodeType>
BSTNodeImpl<T, NodeType>::BSTNodeImpl(T key, NodeType* node) {
    this->right = nullptr;
    this->left = nullptr;
    this->parent = nullptr;
    this->key = key;
    this->counter = 1;
    this->node = node;
}

template<typename T, class NodeType>
NodeType* BSTNodeImpl<T, NodeType>::find_min() {
    return this->left ? this->left->find_min(): this->node;
}

template<typename T, class NodeType>
NodeType* BSTNodeImpl<T, NodeType>::next_larger() {
    if (this->right)
        return this->right->find_min();
    else {
        NodeType *temp = this->node;
        while(temp->get_parent() && temp == temp->get_parent()->get_right()) {
            temp = temp->get_parent();
        }
        return temp->get_parent();
    }
}

template<typename T, class NodeType>
NodeType* BSTNodeImpl<T, NodeType>::remove() {
    if (this->left == nullptr || this->right == nullptr) {
        if(this->node == this->parent->get_left()) {
            this->parent->set_left(this->left ? this->left : this->right);
            if (this->parent->get_left()) {
                this->parent->get_left()->set_parent(this->parent);
            }
        } else {
            this->parent->set_right(this->left ? this->left : this->right);
            if (this->parent->get_right()) {
                this->parent->get_right()->set_parent(this->parent);
            }
        }
        return this->node;
    } else {
        NodeType *temp = this->next_larger();
        T temp_key = temp->get_key(); 
        temp->set_key(this->key);
        this->key = temp_key;
        return temp->remove();
    }        
}

template<typename T, class NodeType>
NodeType* BSTNodeImpl<T, NodeType>::search(T key) {
    if (this->key == key)
        return this->node;
    else if (this->key > key)
        return this->left ? this->left->search(key) : nullptr;
    else if (this->key < key)
        return this->right ? this->right->search(key) : nullptr;
}

template<typename T, class NodeType>
NodeType* BSTNodeImpl<T, NodeType>::insert(T key) {
    if (this->key == key) {
        this->counter++;
        return this->node;
    }
    else if (this->key > key) {
        if (this->left == nullptr) {
            this->left = new NodeType(key);
            this->left = this->node;
            return this->node;
        } else {
            this->left->insert(key);
        }
    } else {
        if (this->right == nullptr) {
            this->right = new NodeType(key);
            this->right = this->node;
            return this->node;
        } else {
            this->right->insert(key);
        }
    }
}

template<typename T, class NodeType>
bool BSTNodeImpl<T, NodeType>::check_ri() {
    if (this->left == nullptr && this->right == nullptr)
        return true;
    if (this->left && this->left->get_key() > this->key)
        return false;
    if (this->right && this->right->get_key() < this->key)
        return false;
    if (this->left && this->right)
        return this->left->check_ri() && this->right->check_ri();
    else if (this->left)
        return this->left->check_ri();
    else
        return this->right->check_ri();
}

template<typename T, class NodeType>
T BSTNodeImpl<T, NodeType>::get_key() {
    return this->key;
}

bst_node.hpp

#pragma once

#include"Impl/bst_node_impl.hpp"
#include"../binary_tree/binary_tree_node.hpp"

template<typename T>
class BSTNode: public BinaryTreeNode<T> {
    public:
        BSTNodeImpl<T, BSTNode<T>>* impl;
        BSTNode();
        BSTNode(T key);
        bool check_ri() override;

        T get_key() override;

        void inorder_print();
        void pre_order_print();
        void post_order_print();

        BSTNode<T>* get_left();
        BSTNode<T>* get_right();
        BSTNode<T>* get_parent();

        BSTNode<T>* insert(T key);
        BSTNode<T>* search(T key);
        BSTNode<T>* remove();
        BSTNode<T>* next_larger();
        BSTNode<T>* find_min();

        void set_parent(void* node) override;
        void set_left(void* node) override;
        void set_right(void* node) override;
};

#include "bst_node.tpp"

bst_node.tpp

template<typename T>
BSTNode<T>::BSTNode(T key) {
    this->impl = new BSTNodeImpl<T, BSTNode<T>>(key, this);
    this->impl->get_key();
}

template<typename T>
BSTNode<T>* BSTNode<T>::find_min() {
    return (BSTNode<T>*)this->impl->find_min();
}

template<typename T>
BSTNode<T>* BSTNode<T>::next_larger() {
    return (BSTNode<T>*)this->impl->next_larger();
}

template<typename T>
BSTNode<T>* BSTNode<T>::remove() {
    return (BSTNode<T>*)this->impl->remove();
}

template<typename T>
BSTNode<T>* BSTNode<T>::search(T key) {
    return (BSTNode<T>*)this->impl->search(key);
}

template<typename T>
BSTNode<T>* BSTNode<T>::insert(T key) {
    return (BSTNode<T>*)this->impl->insert(key);
}

template<typename T>
bool BSTNode<T>::check_ri() {
    return this->impl->check_ri();
}   

template<typename T>
void BSTNode<T>::set_left(void* node) {
    this->impl->set_left((BSTNode<T>*) node);
} 

template<typename T>
void BSTNode<T>::set_parent(void* node) {
    this->impl->set_parent((BSTNode<T>*) node);
}

template<typename T>
void BSTNode<T>::set_right(void* node) {
    this->impl->set_right((BSTNode<T>*) node);
}

template<typename T>
BSTNode<T>* BSTNode<T>::get_right() {
    return (BSTNode<T>*)this->impl->get_right();
} 

template<typename T>
BSTNode<T>* BSTNode<T>::get_left() {
    return (BSTNode<T>*)this->impl->get_left();
} 

template<typename T>
BSTNode<T>* BSTNode<T>::get_parent() {
    return (BSTNode<T>*)this->impl->get_parent();
}

template<typename T>
T BSTNode<T>::get_key() {
    return this->impl->get_key();
}

template<typename T>
void BSTNode<T>::pre_order_print() {
    this->impl->pre_order_print();
}

template<typename T>
void BSTNode<T>::inorder_print() {
    this->impl->inorder_print();
}

template<typename T>
void BSTNode<T>::post_order_print() {
    this->impl->post_order_print();
}

bst.hpp

#pragma once


#include"../binary_tree/binary_tree.hpp"
#include"Impl/bst_impl.hpp"
#include"bst_node.hpp"

template<typename T>
class BST: public BinaryTree<T> {
    public:
        BSTImpl<T, BSTNode<T>> *impl;
        BST();
        BST(T key);
        bool check_ri();
        BSTNode<T>* insert(T key) override;
        BSTNode<T>* search(T key) override;
        BSTNode<T>* remove(T key) override;
};

#include "bst.tpp"

bst.tpp

template<typename T>
BST<T>::BST(){
    this->impl = new BSTImpl<T, BSTNode<T>>();
}

template<typename T>
BST<T>::BST(T key){
    this->impl = new BSTImpl<T, BSTNode<T>>(key);
}

template<typename T>
BSTNode<T>* BST<T>::insert(T key) {
    return this->impl->insert(key);
}

template<typename T>
bool BST<T>::check_ri() {
    return this->impl->check_ri();
}

template<typename T>
BSTNode<T>* BST<T>::search(T key) {
    return this->impl->search(key);
}

template<typename T>
BSTNode<T>* BST<T>::remove(T key) {
    return this->impl->remove(key);
}

main.cpp

#include<bits/stdc++.h>
#include"bst_node.hpp"
#include"bst.hpp"
#include"../utils.hpp"

int  main () {
    std::vector<int> array = get_random_array<int>(10, 100);
    BST<int> *bst = new BST<int>();
    for(auto item: array) {
        bst->insert(item);
        bst->inorder_print();
        bst->check_ri();
    }

}

运行时出现段错误。

0 个答案:

没有答案
相关问题