C中的半inheritance:这个代码片段如何工作?

在C中破解有限forms的多态性的一种方法是执行以下操作:

typedef struct { int x; } base; typedef struct { base super; int y; } derived; 

现在,您可以将派生实例作为基本实例引用,具体取决于变量的转换方式,即:

 derived my_derived; my_derived.y = 10; my_derived.super.x = 20; //will print 10 printf("%d", (&my_derived)->y); //will print 20 printf("%d", ((base*)(&my_derived) )->x); 

所以我的问题是,这究竟是如何工作的? 是因为当你把它作为基础并引用变量时,你引用int成员’x’作为’base’结构开头的偏移量? 这是我唯一能想到的,任何帮助都会受到赞赏。

非常感谢!

在结构中,数据元素之间或结构的末尾可以有未命名的填充字节,但不是在开头。 因此,结构类型对象的第一个数据元素的地址保证与结构类型对象本身的地址相同。

因此,在您的示例中, my_derived的地址与my_derived.super的地址相同。

结构是一个字节区域内存,编译器知道它的结构,即你在里面声明的变量。

例如,您可以声明一个结构:

 struct st { int number; }; struct st n; n.number = 10; printf("n=%i\n", n.number); 

但是您可以更改编译器行为,例如在结构上声明指向char的指针:

 char *c = (char*)&n; printf("char c=%c\n", c[0]); 

这是一份法律声明。 然后你可以随时改变那个记忆区的结构。 唯一重要的是你声明的struct的内存地址。

在您的示例中,当声明派生结构时,程序会保留一个内存区域来分配派生结构,但编译器看到此区域的格式可以随时更改:

 struct derived my_derived; struct base *b = (struct base*)&my_derived; b->x = 20; my_derived.y = 10; printf("x=%iy=%i\n", my_derived.base.x, my_derived.y); 

在这种情况下,b和&my_derived共享相同的内存区域,您只需更改编译器“看到”此区域的方式。

使用“类型双关语”是C语言中的oop遗产模拟的基础,这是一种非oop编程语言。

我在我的项目中使用这种技术: oop4c

是因为当你把它作为基础并引用变量时,你引用int成员’x’作为’base’结构开头的偏移量?

是。 这种技术有时被称为“类型双关语”。

这用于POSIX标准库; 例如,在struct sockaddr中。 通常你将一个声明为sockaddr_storage,将其作为sockaddr传递,并将其作为sockaddr_in或_in6进行操作,具体取决于实际存储在其中的地址类型。