使用结构成员和强制转换结构指针之间的区别;仿效;C中的多态性

使用结构成员和强制转换结构指针之间的区别;仿效;C中的多态性,c,pointers,C,Pointers,我不确定我的措辞在技术上是否正确,所以请在标题和问题的主体部分对我进行更正 所以基本上我的问题是关于在C中模拟多态性。例如,假设我有一棵树,并且有一个struct tree_节点类型。我有一些函数可以帮助我插入节点、删除节点等,例如: void tree_insert(tree_node **root, tree_node *new_node); 然后我开始为我的应用程序构建其他东西,并且需要使用这个树来维护,比如说,家庭成员。但对于人类,我有另一个结构,我们称之为“struct human_

我不确定我的措辞在技术上是否正确,所以请在标题和问题的主体部分对我进行更正

所以基本上我的问题是关于在C中模拟多态性。例如,假设我有一棵树,并且有一个struct tree_节点类型。我有一些函数可以帮助我插入节点、删除节点等,例如:

void tree_insert(tree_node **root, tree_node *new_node);
然后我开始为我的应用程序构建其他东西,并且需要使用这个树来维护,比如说,家庭成员。但对于人类,我有另一个结构,我们称之为“struct human_node”,定义如下,例如:

typedef struct human_node_ {
    tree_node t_node;
    char *name;
} human_node;
现在显然我想使用我为泛型树构建的那些树实用程序函数。但它们使用树节点指针。现在是进行多态性仿真的时候了。这里有两个选项,一个是强制转换我的human_节点,一个是在human_节点中使用t_节点成员:

human_node *myfamily_tree_root, *new_family_guy;
//some initialization code and other code later...
tree_insert((tree_node **)&myfamily_tree_root, &(new_family_guy->t_node));
为了简洁起见,我在上面的一个函数调用中使用了两种方法


这正是我困惑的地方。因此,我应该使用哪一种,更重要的是,为什么使用?

两者都是标准的,但一般来说,如果可以避免类型转换,那么应该选择避免类型转换的解决方案

这种内联数据结构实现的一个常见问题是,甚至不要求树节点(或等效节点)是结构中的第一个元素,因为您可能希望将节点输入到多个树中。那么你肯定要使用第二种方法。要在tree_node元素和包含该元素的结构之间进行转换,必须使用一些黑魔法宏,但这是值得的。例如,在avl树的实现中,我有以下宏:

#ifndef offsetof
#define offsetof(s, e) ((size_t)&((s *)0)->e)
#endif

/* the bit at the end is to prevent mistakes where n is not an avl_node */
#define avl_data(n, type, field) ((type *)(void*)((char *)n - offsetof(type, field) - (n - (struct avl_node *)n)))
所以我可以吃一些像:

struct foo {
    int data;
    struct avl_node tree_node_1;
    struct avl_node tree_node_2;
};

int
tree_node_1_to_data(struct avl_node *x)
{
     return avl_data(x, struct foo, tree_node_1)->data;
}

如果您选择将代码设置为这种泛型,那么您肯定希望引用树节点成员,而不是将指针类型转换为结构。

对于任何特定的答案来说,这个问题可能过于宽泛,但您可以看到例如

基本上,所有Python结构都有相同的头,要定义自己的类型,必须确保在结构开始时使用(或
PyObject\u VAR\u HEAD
用于大小可变的对象,如字符串)。这会添加类型标记、引用计数等内容

实例化对象后,将它们作为
PyObject*
s传递,函数将推断对象的实际类型(例如字符串、列表等),并能够基于该类型进行调度。是的,您必须在某个时候键入cast才能获得实际的对象内容

例如,这是:

你可以阅读更多关于这本书的内容。摘录:

对象总是通过“PyObject*”类型的指针访问。 类型“PyObject”是仅包含引用的结构 计数和类型指针。为对象分配的实际内存 包含只有在强制转换后才能访问的其他数据 指向指向较长结构类型的指针


请注意,此攻角可能更适合解释代码。您可能会看到其他与您的需求更直接相关的开源项目。

C中没有模板符号,您必须为每个不同的指针类型定义单独的函数,但实际上,除非编译器对类型检查过于严格,您可以向函数传递任何指针类型,然后将该指针视为指向所需的任何对象,因为指针就是指针,如果您知道mean@mangusta我想我知道你的意思,我不确定我是否同意必须为每个不同的指针类型定义一个单独的函数。您可以将此作为参考进行检查:您是对的,它可能太宽泛,无法给出具体的答案。嘿,但到目前为止我得到了很好的资源。你提到了CPython,@Art展示了一些非常酷的东西@是的,让我们看看它是如何调节的:)我认为这是一个有用的问题!我认为你是对的。我提到的两种方法是相同的,当需要在这两种方法之间做出决定时,避免铸造可能是一个很好的规则。
typedef struct {
    PyObject_VAR_HEAD
    Py_hash_t ob_shash;
    char ob_sval[1];

    /* Invariants:
     *     ob_sval contains space for 'ob_size+1' elements.
     *     ob_sval[ob_size] == 0.
     *     ob_shash is the hash of the string or -1 if not computed yet.
     */
} PyBytesObject;