首页 > 解决方案 > 我可以限制多态性的行为吗?

问题描述

所以我正在尝试实现二叉搜索树和avl树。这些类中的每一个都使用不同但相似类型的节点。节点的类如下所示:

class node
{
protected:
    int key;
    node* parent, * left, * right;
public:
    node(int key, node* parent = nullptr) :key(key), parent(parent), left(nullptr), right(nullptr) {}
    ~node() {}
};

class avl_node : public node
{
private:
    int height;
public:
    avl_node(int key, int height, avl_node* parent = nullptr) :node(key, parent), height(height) {}
    ~avl_node() {}
};

这主要是有效的。Anynode可以与 any other 有联系node,并且 anyavl_node与 any other有联系avl_node。我想到的问题是,由于多态性,anode在技术上可能有一个或多个父avl_node级,我不希望这种情况发生。虽然我可以通过小心来避免这种情况,但我根本不希望它成为可能。有办法吗?
ps我想保持类相关

标签: c++classinheritancepolymorphismnodes

解决方案


如果足够,您可以显式删除将采用的构造函数版本avl_node*

class node
{
protected:
    int key;
    node* parent, * left, * right;
public:
    node(int key, node* parent = nullptr) :key(key), parent(parent), left(nullptr), right(nullptr) {}
    node(int, avl_node*) = delete;
    ~node() {}
};

当然,这种解决方案并非万无一失。如果您在指针avl_node后面带了一个隐藏node项,编译器将无法分辨(并且由于多态性主要是动态的,因此您只会在尝试直接分配指针的特定情况下受到保护)

这将编译。

avl_node myavl;
node n(0, static_cast<node*>(&myavl));

您可以尝试在node构造函数中进行动态转换以判断它是否avl_node被传递(您的节点需要一个 vtable),但这将使得无法从avl_node构造函数中调用构造函数。

另一种选择是制作一个专门用于子类的单独构造函数

class node
{
protected:
    int key;
    node* parent, * left, * right;
    node(int key, avl_node* parent) : key(key), parent(parent), left(nullptr), right(nullptr) {}
public:
    node(int key, node* parent = nullptr) :key(key), parent(parent), left(nullptr), right(nullptr) { /* do something to not allow avl_node* to be passed */ }
    ~node() {}
};

推荐阅读