[英]can i restrict behaviour of polymorphism?
So i'm trying to implement a binary search tree and avl tree.所以我正在尝试实现二叉搜索树和avl树。 Each of these classes using different but similar types of nodes.
这些类中的每一个都使用不同但相似类型的节点。 The classes for nodes look like this:
节点的类如下所示:
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() {}
};
This mostly works.这主要是有效的。 Any
node
can have connexions with any other node
, and any avl_node
with any other avl_node
.任何
node
都可以与任何其他node
建立联系,任何avl_node
可以与任何其他avl_node
建立联系。 The issue that I think of is that a node
could technically have a parent or children avl_node
because of polymorphism, and I wouldn't want that to happen.我想到的问题是,由于多态性,一个
node
在技术上可能有一个父节点或子节点avl_node
,我不希望这种情况发生。 Although I can avoid that by being careful, i wouldn't want it to be possible at all.虽然我可以通过小心来避免这种情况,但我根本不希望它成为可能。 Is there a way?
有办法吗?
ps I want to keep the classes related ps我想保持类相关
If it's enough, you could explicitly delete the version of constructor that would take an avl_node*
如果足够,您可以显式删除将采用
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() {}
};
Of course, this solution is not foolproof.当然,这种解决方案并非万无一失。 If you brought an
avl_node
hidden behind a node
pointer, the compiler wouldn't be able to tell (and since polymorphism is mainly dynamic, you would only be protected in this specific case where you attempt to assign the pointer directly)如果您将
avl_node
隐藏在node
指针后面,编译器将无法判断(并且由于多态性主要是动态的,因此您只会在尝试直接分配指针的特定情况下受到保护)
This would compile.这将编译。
avl_node myavl;
node n(0, static_cast<node*>(&myavl));
You could try dynamic-casting in the node
constructor to tell if it's an avl_node
being passed (your nodes would need a vtable for that), but that would make it impossible to call the constructor like that from the avl_node
constructor.您可以尝试在
node
构造函数中进行动态转换,以判断它是否是传递的avl_node
(您的节点需要一个 vtable),但这将使得无法像从avl_node
构造函数那样调用构造函数。
Another option would be making a separate constructor intended specifically for the subclass另一种选择是制作一个专门用于子类的单独构造函数
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() {}
};
You can get rid of polymorphism and avoid code duplication by using a class template for the base, and members that depend on the template argument.您可以通过使用 class 模板作为基类和依赖于模板参数的成员来摆脱多态性并避免代码重复。
Example:例子:
template<typename T>
class node
{
protected:
int key;
node* parent, * left, * right; // Note: these are actually 'node<T>'.
public:
node(int key, node* parent = nullptr)
: key(key), parent(parent), left(nullptr), right(nullptr) {}
void set_parent(node* p) { parent = p; }
};
class avl_node : public node<avl_node>
{
private:
int height;
public:
avl_node(int key, int height, avl_node* parent = nullptr)
: node(key, parent), height(height) {}
};
class silly_node : public node<silly_node>
{
public:
silly_node() : node(0) {}
};
int main()
{
// Fine
avl_node an(0, 1);
// Fine
avl_node bn(0, 1, &an);
// Also fine
bn.set_parent(&an);
// Fine
silly_node sn;
// Compilation error
avl_node cn(0, 1, &sn);
// Also compilation error
bn.set_parent(&sn);
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.