C语言可以实现多态,但必须保证子类和父类相同的元素放在结构体最前面,且必须一模一样的排序。

This commit is contained in:
建峰 2024-09-01 13:36:12 +08:00
parent 2aca923437
commit 5d6d031a3a

20
main.c
View File

@ -41,19 +41,19 @@ struct _virtual_table *virtual_new(void)
struct _shape struct _shape
{ {
struct _virtual_table *vtb; struct _virtual_table vtb;
}; };
void shape_area(void *self) void shape_area(void *self)
{ {
struct _shape *pthis = (struct _shape *)self; struct _shape *pthis = (struct _shape *)self;
pthis->vtb->area(self); pthis->vtb.area(self);
} }
void shape_draw(void *self) void shape_draw(void *self)
{ {
struct _shape *pthis = (struct _shape *)self; struct _shape *pthis = (struct _shape *)self;
pthis->vtb->draw(self); pthis->vtb.draw(self);
} }
PRIVATE void _shape_area(void *self) PRIVATE void _shape_area(void *self)
@ -77,12 +77,10 @@ struct _shape *shape_new(void)
.area = (void (*)(void *self))_shape_area, .area = (void (*)(void *self))_shape_area,
.draw = (void (*)(void *self))_shape_draw .draw = (void (*)(void *self))_shape_draw
}; };
shape->vtb = &vtb; shape->vtb = vtb;
return shape; return shape;
} }
#define SUPER(self) (&(self)->shape)
#if 0 #if 0
void shape_free(struct _shape * self) void shape_free(struct _shape * self)
{ {
@ -96,7 +94,8 @@ void shape_free(struct _shape * self)
struct _rect struct _rect
{ {
// super // super
struct _shape shape; // struct _shape shape;
struct _virtual_table vtb;
// attribute // attribute
double width, height; double width, height;
@ -131,14 +130,15 @@ struct _rect *rect_new(double width, double height)
.draw = (void (*)(void *self))rect_draw .draw = (void (*)(void *self))rect_draw
}; };
SUPER(rect)->vtb = &vtb; rect->vtb = vtb;
return rect; return rect;
} }
struct _circle struct _circle
{ {
// super // super
struct _shape shape; // struct _shape shape;
struct _virtual_table vtb;
// attribute // attribute
double radius; double radius;
@ -171,7 +171,7 @@ struct _circle *circle_new(double radius)
.draw = (void (*)(void *self))circle_draw, .draw = (void (*)(void *self))circle_draw,
}; };
SUPER(circle)->vtb = &vtb; circle->vtb = vtb;
return circle; return circle;
} }