mirror of
https://gitee.com/apaki/cmake_demo.git
synced 2025-05-18 04:11:37 +08:00
实现了多态,但是只能单继承,且父类必须放在子类最开头。
This commit is contained in:
parent
7021105e64
commit
52155db7e8
106
main.c
106
main.c
@ -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;
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user