实现了多态,但是只能单继承,且父类必须放在子类最开头。

This commit is contained in:
建峰 2024-09-01 04:00:56 +08:00
parent 7021105e64
commit 52155db7e8

106
main.c
View File

@ -6,7 +6,10 @@
#include <assert.h> #include <assert.h>
#define VIRTUAL #define VIRTUAL
#define PRIVATE #define PRIVATE static
#define ASSERT_CALL_VIRTUAL_METHOD() assert(!("can't call abstract method"))
struct _virtual_table struct _virtual_table
{ {
@ -16,42 +19,51 @@ struct _virtual_table
void virtual_area(void *self) void virtual_area(void *self)
{ {
assert(!"can't call abstract method"); ASSERT_CALL_VIRTUAL_METHOD();
} }
void virtual_draw(void *self) void virtual_draw(void *self)
{ {
assert(!"can't call abstract method"); ASSERT_CALL_VIRTUAL_METHOD();
} }
struct _virtual_table *virtual_new(void) struct _virtual_table *virtual_new(void)
{ {
struct _virtual_table *v = calloc(1, sizeof(struct _virtual_table)); struct _virtual_table *vtb = calloc(1, sizeof(struct _virtual_table));
if (v == NULL) if (vtb == NULL)
{ {
return NULL; return NULL;
} }
v->area = virtual_area; vtb->area = virtual_area;
v->draw = virtual_draw; vtb->draw = virtual_draw;
return v; return vtb;
} }
struct _shape struct _shape
{ {
VIRTUAL void (*area)(void *self); struct _virtual_table *vtb;
VIRTUAL void (*draw)(void *self);
}; };
void shape_area(void *self) void shape_area(void *self)
{ {
assert(!"can't call abstract method"); struct _shape *this = (struct _shape *)self;
this->vtb->area(self);
} }
void shape_draw(void *self) void shape_draw(void *self)
{ {
assert(!"can't call abstract method"); struct _shape *this = (struct _shape *)self;
this->vtb->draw(self);
}
PRIVATE void _shape_area(void *self)
{
ASSERT_CALL_VIRTUAL_METHOD();
}
PRIVATE void _shape_draw(void *self)
{
ASSERT_CALL_VIRTUAL_METHOD();
} }
struct _shape *shape_new(void) struct _shape *shape_new(void)
@ -61,11 +73,16 @@ struct _shape *shape_new(void)
{ {
return NULL; return NULL;
} }
shape->area = shape_area; static struct _virtual_table vtb = {
shape->draw = shape_draw; .area = (void (*)(void *self))_shape_area,
.draw = (void (*)(void *self))_shape_draw
};
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)
{ {
@ -76,12 +93,10 @@ void shape_free(struct _shape * self)
} }
#endif #endif
#define SUPER(self) ((self)->shape)
struct _rect struct _rect
{ {
// super // super
struct _shape* shape; struct _shape shape;
// attribute // attribute
double width, height; double width, height;
@ -111,21 +126,19 @@ struct _rect *rect_new(double width, double height)
rect->width = width; rect->width = width;
rect->height = height; rect->height = height;
rect->shape = shape_new(); static struct _virtual_table vtb = {
if (rect->shape == NULL) .area = (void (*)(void *self))rect_area,
{ .draw = (void (*)(void *self))rect_draw
return NULL; };
}
SUPER(rect)->area = (void (*)(void *self))rect_area; SUPER(rect)->vtb = &vtb;
SUPER(rect)->draw = (void (*)(void *self))rect_draw;
return rect; return rect;
} }
struct _circle struct _circle
{ {
// super // super
struct _shape *shape; struct _shape shape;
// attribute // attribute
double radius; double radius;
@ -151,16 +164,14 @@ struct _circle *circle_new(double radius)
{ {
return NULL; return NULL;
} }
circle->shape = shape_new();
if (circle->shape == NULL)
{
return NULL;
}
circle->radius = radius; circle->radius = radius;
SUPER(circle)->area = (void (*)(void *self))circle_area; static struct _virtual_table vtb = {
SUPER(circle)->draw = (void (*)(void *self))circle_draw; .area = (void (*)(void *self))circle_area,
.draw = (void (*)(void *self))circle_draw,
};
SUPER(circle)->vtb = &vtb;
return circle; return circle;
} }
@ -174,15 +185,28 @@ int main(int argc, char *argv[])
circle_area(circle); circle_area(circle);
circle_draw(circle); circle_draw(circle);
// struct shape *shape = shape_new(); printf("------------------------------\n");
// shape_area(shape); shape_area(rect);
// shape_draw(shape); shape_area(circle);
// struct _shape *shape = NULL; shape_draw(rect);
struct _shape *shape = rect_new(2,3); shape_draw(circle);
// shape = rect;
printf("------------------------------\n");
struct _shape *shape = (struct _shape *)rect_new(2,3);
shape_area(shape); shape_area(shape);
shape_draw(shape); shape_draw(shape);
struct _shape *shape2 = NULL;
shape2 = (struct _shape *)circle;
shape_area(shape2);
shape_draw(shape2);
printf("------------------------------\n");
struct _shape *shape3 = shape_new();
shape_area(shape3);
shape_draw(shape3);
return 0; return 0;
} }