From 52155db7e85d56012509e263d194247b7c74bfe7 Mon Sep 17 00:00:00 2001 From: jf-home Date: Sun, 1 Sep 2024 04:00:56 +0800 Subject: [PATCH] =?UTF-8?q?=E5=AE=9E=E7=8E=B0=E4=BA=86=E5=A4=9A=E6=80=81?= =?UTF-8?q?=EF=BC=8C=E4=BD=86=E6=98=AF=E5=8F=AA=E8=83=BD=E5=8D=95=E7=BB=A7?= =?UTF-8?q?=E6=89=BF=EF=BC=8C=E4=B8=94=E7=88=B6=E7=B1=BB=E5=BF=85=E9=A1=BB?= =?UTF-8?q?=E6=94=BE=E5=9C=A8=E5=AD=90=E7=B1=BB=E6=9C=80=E5=BC=80=E5=A4=B4?= =?UTF-8?q?=E3=80=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- main.c | 106 +++++++++++++++++++++++++++++++++++---------------------- 1 file changed, 65 insertions(+), 41 deletions(-) diff --git a/main.c b/main.c index c99c985..e432cf7 100644 --- a/main.c +++ b/main.c @@ -6,7 +6,10 @@ #include #define VIRTUAL -#define PRIVATE +#define PRIVATE static + +#define ASSERT_CALL_VIRTUAL_METHOD() assert(!("can't call abstract method")) + struct _virtual_table { @@ -16,42 +19,51 @@ struct _virtual_table void virtual_area(void *self) { - assert(!"can't call abstract method"); + ASSERT_CALL_VIRTUAL_METHOD(); } void virtual_draw(void *self) { - assert(!"can't call abstract method"); + ASSERT_CALL_VIRTUAL_METHOD(); } struct _virtual_table *virtual_new(void) { - struct _virtual_table *v = calloc(1, sizeof(struct _virtual_table)); - if (v == NULL) + struct _virtual_table *vtb = calloc(1, sizeof(struct _virtual_table)); + if (vtb == NULL) { return NULL; } - v->area = virtual_area; - v->draw = virtual_draw; - return v; + vtb->area = virtual_area; + vtb->draw = virtual_draw; + return vtb; } - - struct _shape { - VIRTUAL void (*area)(void *self); - VIRTUAL void (*draw)(void *self); + struct _virtual_table *vtb; }; 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) { - 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) @@ -61,11 +73,16 @@ struct _shape *shape_new(void) { return NULL; } - shape->area = shape_area; - shape->draw = shape_draw; + static struct _virtual_table vtb = { + .area = (void (*)(void *self))_shape_area, + .draw = (void (*)(void *self))_shape_draw + }; + shape->vtb = &vtb; return shape; } +#define SUPER(self) (&(self)->shape) + #if 0 void shape_free(struct _shape * self) { @@ -76,12 +93,10 @@ void shape_free(struct _shape * self) } #endif -#define SUPER(self) ((self)->shape) - struct _rect { // super - struct _shape* shape; + struct _shape shape; // attribute double width, height; @@ -111,21 +126,19 @@ struct _rect *rect_new(double width, double height) rect->width = width; rect->height = height; - rect->shape = shape_new(); - if (rect->shape == NULL) - { - return NULL; - } + static struct _virtual_table vtb = { + .area = (void (*)(void *self))rect_area, + .draw = (void (*)(void *self))rect_draw + }; - SUPER(rect)->area = (void (*)(void *self))rect_area; - SUPER(rect)->draw = (void (*)(void *self))rect_draw; + SUPER(rect)->vtb = &vtb; return rect; } struct _circle { // super - struct _shape *shape; + struct _shape shape; // attribute double radius; @@ -151,16 +164,14 @@ struct _circle *circle_new(double radius) { return NULL; } - circle->shape = shape_new(); - if (circle->shape == NULL) - { - return NULL; - } - circle->radius = radius; - SUPER(circle)->area = (void (*)(void *self))circle_area; - SUPER(circle)->draw = (void (*)(void *self))circle_draw; + static struct _virtual_table vtb = { + .area = (void (*)(void *self))circle_area, + .draw = (void (*)(void *self))circle_draw, + }; + + SUPER(circle)->vtb = &vtb; return circle; } @@ -174,15 +185,28 @@ int main(int argc, char *argv[]) circle_area(circle); circle_draw(circle); - // struct shape *shape = shape_new(); - // shape_area(shape); - // shape_draw(shape); + printf("------------------------------\n"); + shape_area(rect); + shape_area(circle); - // struct _shape *shape = NULL; - struct _shape *shape = rect_new(2,3); - // shape = rect; + shape_draw(rect); + shape_draw(circle); + + printf("------------------------------\n"); + struct _shape *shape = (struct _shape *)rect_new(2,3); shape_area(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; }