请考虑以下代码。
enum type {CONS, ATOM, FUNC, LAMBDA};
typedef struct{
enum type type;
} object;
typedef struct {
enum type type;
object *car;
object *cdr;
} cons_object;
object *cons (object *first, object *second) {
cons_object *ptr = (cons_object *) malloc (sizeof (cons_object));
ptr->type = CONS;
ptr->car = first;
ptr->cdr = second;
return (object *) ptr;
}
在cons
函数中,变量ptr
的类型是cons_object*
。但是在返回值中它被转换为object*
类型。
- 我想知道这怎么可能,因为
cons_object
和object
是不同的结构。 - 这样做有什么问题吗?
任何想法!
最佳答案
这很好,并且是在 C 中实现“面向对象”的相当普遍的技术。因为 struct
的内存布局在 C 中定义明确,只要两个对象共享相同的布局,那么您可以安全地在它们之间转换指针。也就是说,type
成员的偏移量在 object
结构中与在 cons_object
结构中相同。
在这种情况下,type
成员告诉 API object
是 cons_object
还是 foo_object
或者一些其他类型的对象,所以你可能会看到这样的东西:
void traverse(object *obj)
{
if (obj->type == CONS) {
cons_object *cons = (cons_object *)obj;
traverse(cons->car);
traverse(cons->cdr);
} else if (obj->type == FOO) {
foo_object *foo = (foo_object *)obj;
traverse_foo(foo);
} else ... etc
}
更常见的是,我似乎将“父”类定义为“子”类的第一个成员的实现,如下所示:
typedef struct {
enum type type;
} object;
typedef struct {
object parent;
object *car;
object *cdr;
} cons_object;
这在很大程度上以相同的方式工作,除了您有一个强有力的保证,即子“类”的内存布局将与父类相同。也就是说,如果您将一个成员添加到“基础”对象
,它会自动被子项拾取,您无需手动确保所有结构都同步。
关于将一个结构指针转换为另一个 - C,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3766229/