可以访问继承结构的结构
Struct with access to inherited struct
我正在尝试编写一些函数来处理平衡二叉树。
首先我写了一个典型的二叉树界面。这封装了与二叉树相关的一般功能。
树有节点
typedef struct Node
{
Node* left;
Node* right;
Node* parent;
int key;
void* value;
} Node;
和一些执行 insert
、remove
和 search
的函数。
现在我想扩展该接口以处理不同类型的二叉树,它继承了 Node
。
typedef enum Color
{
RED,
BLACK
} Color;
typedef struct RBTreeNode
{
Node* genericNode;
Color color;
} RBTreeNode;
RBTree
指的是Red-Black Trees
当我尝试编写一个 "tree repair" 函数时,问题接踵而至。
void repairRBTree(Node* nodeInserted)
{
// If nodeInserted's parent is NULL, nodeInserted is the root of the tree.
// Red-Black tree properties suggest root node's color be black.
if (nodeInserted->parent == NULL)
{
RBTreeNode* nodeInsertedTC = (RBTreeNode*)nodeInserted;
nodeInsertedTC->color = BLACK;
}
// If nodeInserted's parent's color is BLACK, nodeInserted has replaced a RED NULL node.
// Red-Black tree properties suggest RED node's parent be BLACK,
// which is the case currently, so there's nothing to be done.
else if (nodeInserted->parent->(COLOR??))
{
return;
}
}
在这个 if
语句中,
if (nodeInserted->parent == NULL)
{
RBTreeNode* nodeInsertedTC = (RBTreeNode*)nodeInserted;
nodeInsertedTC->color = BLACK;
}
如果我之前将 nodeInserted
转换为 Node*
,这意味着指针本身是一个 RBTreeNode*
,所以如果我的想法是正确的,将其转换回 RBTreeNode*
应该做我认为应该做的事。
但是这里
// If nodeInserted's parent's color is BLACK, nodeInserted has replaced a RED NULL node.
// Red-Black tree properties suggest RED node's parent be BLACK,
// which is the case currently, so there's nothing to be done.
else if (nodeInserted->parent->(COLOR??))
{
return;
}
}
我无权访问 nodeInserted->parent
的 Color
枚举。而且我认为将其转换为 RBTreeNode
不会有太大好处。
我知道唯一可行的解决方案是重写我所有的通用函数以将 RBTreeNode
作为参数而不是 Node
,但我真的不想那样做。
有更好的解决方案吗?
您不应该使用指针来实现继承。使用 Node
字段而不是指针:
typedef struct RBTreeNode
{
Node genericNode;
Color color;
} RBTreeNode;
这样,当您将 Node*
转换为 RBTreeNode*
时,它将可以访问 RBTreeNode
的所有字段。
由于您可能使用的是 C++ 编译器,因此类比 C++ 可能会有所帮助。具有 Node
类型的第一个字段就像在 C++ 中具有继承,即 struct RBTreeNode: Node
。具有指针类型的第一个字段就像具有虚拟继承,即 struct RBTreeNode: virtual Node
。两种方法都有效,直到你需要沮丧。 c++ 中的虚拟继承提醒 reader 你的继承层次结构有问题 ("diamond inheritance"),所以你应该只在正常继承不起作用时才使用它。
我正在尝试编写一些函数来处理平衡二叉树。
首先我写了一个典型的二叉树界面。这封装了与二叉树相关的一般功能。
树有节点
typedef struct Node
{
Node* left;
Node* right;
Node* parent;
int key;
void* value;
} Node;
和一些执行 insert
、remove
和 search
的函数。
现在我想扩展该接口以处理不同类型的二叉树,它继承了 Node
。
typedef enum Color
{
RED,
BLACK
} Color;
typedef struct RBTreeNode
{
Node* genericNode;
Color color;
} RBTreeNode;
RBTree
指的是Red-Black Trees
当我尝试编写一个 "tree repair" 函数时,问题接踵而至。
void repairRBTree(Node* nodeInserted)
{
// If nodeInserted's parent is NULL, nodeInserted is the root of the tree.
// Red-Black tree properties suggest root node's color be black.
if (nodeInserted->parent == NULL)
{
RBTreeNode* nodeInsertedTC = (RBTreeNode*)nodeInserted;
nodeInsertedTC->color = BLACK;
}
// If nodeInserted's parent's color is BLACK, nodeInserted has replaced a RED NULL node.
// Red-Black tree properties suggest RED node's parent be BLACK,
// which is the case currently, so there's nothing to be done.
else if (nodeInserted->parent->(COLOR??))
{
return;
}
}
在这个 if
语句中,
if (nodeInserted->parent == NULL)
{
RBTreeNode* nodeInsertedTC = (RBTreeNode*)nodeInserted;
nodeInsertedTC->color = BLACK;
}
如果我之前将 nodeInserted
转换为 Node*
,这意味着指针本身是一个 RBTreeNode*
,所以如果我的想法是正确的,将其转换回 RBTreeNode*
应该做我认为应该做的事。
但是这里
// If nodeInserted's parent's color is BLACK, nodeInserted has replaced a RED NULL node.
// Red-Black tree properties suggest RED node's parent be BLACK,
// which is the case currently, so there's nothing to be done.
else if (nodeInserted->parent->(COLOR??))
{
return;
}
}
我无权访问 nodeInserted->parent
的 Color
枚举。而且我认为将其转换为 RBTreeNode
不会有太大好处。
我知道唯一可行的解决方案是重写我所有的通用函数以将 RBTreeNode
作为参数而不是 Node
,但我真的不想那样做。
有更好的解决方案吗?
您不应该使用指针来实现继承。使用 Node
字段而不是指针:
typedef struct RBTreeNode
{
Node genericNode;
Color color;
} RBTreeNode;
这样,当您将 Node*
转换为 RBTreeNode*
时,它将可以访问 RBTreeNode
的所有字段。
由于您可能使用的是 C++ 编译器,因此类比 C++ 可能会有所帮助。具有 Node
类型的第一个字段就像在 C++ 中具有继承,即 struct RBTreeNode: Node
。具有指针类型的第一个字段就像具有虚拟继承,即 struct RBTreeNode: virtual Node
。两种方法都有效,直到你需要沮丧。 c++ 中的虚拟继承提醒 reader 你的继承层次结构有问题 ("diamond inheritance"),所以你应该只在正常继承不起作用时才使用它。