cmake_demo/main.c
2024-09-01 16:54:38 +08:00

357 lines
7.6 KiB
C

#include <stdint.h>
#include <stdio.h>
#include <stdbool.h>
#include <stdlib.h>
#include <assert.h>
#define VIRTUAL
#define PRIVATE static
#define ASSERT_CALL_VIRTUAL_METHOD() assert(!("can't call abstract method"))
struct _virtual_table
{
VIRTUAL double (*area)(void *self, void *parent);
VIRTUAL void (*draw)(void *self, void *parent);
};
double virtual_area(void *self, void *parent)
{
ASSERT_CALL_VIRTUAL_METHOD();
}
void virtual_draw(void *self, void *parent)
{
ASSERT_CALL_VIRTUAL_METHOD();
}
struct _virtual_table *virtual_new(void)
{
struct _virtual_table *vtb = calloc(1, sizeof(struct _virtual_table));
if (vtb == NULL)
{
return NULL;
}
vtb->area = virtual_area;
vtb->draw = virtual_draw;
return vtb;
}
struct _shape
{
struct _virtual_table vtb;
};
double shape_area(void *self, void *parent)
{
double area = 0;
struct _shape *pthis = (struct _shape *)parent;
area = pthis->vtb.area(self, NULL);
return area;
}
void shape_draw(void *self, void *parent)
{
struct _shape *pthis = (struct _shape *)parent;
pthis->vtb.draw(self, NULL);
}
PRIVATE double _shape_area(void *self, void *parent)
{
ASSERT_CALL_VIRTUAL_METHOD();
}
PRIVATE void _shape_draw(void *self, void *parent)
{
ASSERT_CALL_VIRTUAL_METHOD();
}
struct _shape *shape_new(void)
{
struct _shape *shape = calloc(1, sizeof(struct _shape));
if(shape == NULL)
{
return NULL;
}
static struct _virtual_table vtb = {
.area = (double (*)(void *self, void *parent))_shape_area,
.draw = (void (*)(void *self, void *parent))_shape_draw
};
shape->vtb = vtb;
return shape;
}
#if 0
void shape_free(struct _shape * self)
{
if (self != NULL)
{
free(self);
}
}
#endif
struct _rect
{
int invalid;
// super
struct _shape *shape;
// struct _shape;
// struct _virtual_table vtb;
// attribute
double width, height;
// method
// void (*area)(void *self);
// void (*draw)(void *self);
};
double rect_area(void *self, void *parent)
{
double area = 0;
struct _rect *pthis = (struct _rect *)parent;
area = pthis->shape->vtb.area(self, NULL);
return area;
}
void rect_draw(void *self, void *parent)
{
struct _rect *pthis = (struct _rect *)parent;
pthis->shape->vtb.draw(self, NULL);
}
double _rect_area(void *self, void *parent)
{
struct _rect *pthis = (struct _rect *)self;
double area = pthis->width * pthis->height;
printf("rect area = %0.2f\n", area);
return area;
}
void _rect_draw(void *self, void *parent)
{
printf("rect draw\n");
}
struct _rect *rect_new(double width, double height)
{
// super
static struct _virtual_table vtb = {
.area = (double (*)(void *self, void *parent))_rect_area,
.draw = (void (*)(void *self, void *parent))_rect_draw,
};
struct _shape *shape = shape_new();
if (shape == NULL)
{
return NULL;
}
shape->vtb = vtb;
// self
struct _rect *rect = calloc(1, sizeof(struct _rect));
if (rect == NULL)
{
return NULL;
}
rect->width = width;
rect->height = height;
// set parent
rect->shape = shape;
return rect;
}
struct _circle
{
int invalid;
// super
struct _shape *shape;
// attribute
double radius;
// method
// void (*area)(void *self);
// void (*draw)(void *self);
};
double circle_area(void *self, void *parent)
{
double area = 0;
struct _circle *pthis = (struct _circle *)parent;
area = pthis->shape->vtb.area(self, NULL);
return area;
}
void circle_draw(void *self, void *parent)
{
struct _circle *pthis = (struct _circle *)parent;
pthis->shape->vtb.draw(self, NULL);
}
double _circle_area(void *self, void *parent)
{
struct _circle *pthis = (struct _circle *)self;
double area = 3.14 * pthis->radius * pthis->radius;
printf("circle area = %0.2f\n", area);
return area;
}
void _circle_draw(void *self, void *parent)
{
printf("circle draw\n");
}
struct _circle *circle_new(double radius)
{
// super
static struct _virtual_table vtb = {
.area = (double (*)(void *self, void *parent))_circle_area,
.draw = (void (*)(void *self, void *parent))_circle_draw,
};
struct _shape *shape = shape_new();
if (shape == NULL)
{
return NULL;
}
shape->vtb = vtb;
// self
struct _circle *circle = calloc(1, sizeof(struct _circle));
if (circle == NULL)
{
return NULL;
}
circle->radius = radius;
// set parent
circle->shape = shape;
return circle;
}
struct _copper_cash
{
struct _shape *shape;
struct _rect *rect;
struct _circle *circle;
double price;
};
double copper_cash_area(struct _copper_cash *self, void *parent)
{
// 如果用的继承,那么就不能直接调用父类的虚接口,实现自己。
// 因为父类虚接口,是自己实现的。这样相当于自己调用自己。导致卡死。
// double circle_area = self->circle->shape->vtb.area(self->circle, self->circle);
// double rect_area = self->rect->shape->vtb.area(self->rect, self->rect);
double circle_area = 3.14 * self->circle->radius * self->circle->radius;
double rect_area = self->rect->width * self->rect->height;
double area = circle_area - rect_area;
printf("copper cash area = %0.2f\n", circle_area - rect_area);
return area;
}
void copper_cash_draw(struct _copper_cash *self, void *parent)
{
printf("copper cash draw\n");
}
struct _copper_cash *copper_cash_new(double width, double height, double radius)
{
// super
static struct _virtual_table vtb = {
.area = (double (*)(void *self, void *parent))copper_cash_area,
.draw = (void (*)(void *self, void *parent))copper_cash_draw,
};
struct _shape *shape = shape_new();
if (shape == NULL)
{
return NULL;
}
shape->vtb = vtb;
struct _rect *rect = rect_new(width, height);
if(rect == NULL)
{
return NULL;
}
rect->shape = shape;
struct _circle *circle = circle_new(radius);
if (circle == NULL)
{
return NULL;
}
circle->shape = shape;
// self
struct _copper_cash *cc = calloc(1, sizeof(struct _copper_cash));
if (cc == NULL)
{
return NULL;
}
cc->price = 100;
// set parent
cc->shape = shape;
cc->rect = rect;
cc->circle = circle;
return cc;
}
int main(int argc, char *argv[])
{
struct _rect *rect = rect_new(4, 5);
rect_area(rect, rect);
rect_draw(rect, rect);
struct _circle *circle = circle_new(3);
circle_area(circle, circle);
circle_draw(circle, circle);
printf("----- rect & circle -----\n");
shape_area(rect, rect->shape);
shape_draw(rect, rect->shape);
shape_area(circle, circle->shape);
shape_draw(circle, circle->shape);
printf("----- [2] rect & circle -----\n");
struct _rect *rect2 = (struct _rect *)rect_new(2, 3);
shape_area(rect2, rect2->shape);
shape_draw(rect2, rect2->shape);
struct _circle *circle2 = (struct _circle *)circle_new(1);
shape_area(circle2, circle->shape);
shape_draw(circle2, circle->shape);
// printf("----- [2] shape -----\n");
// struct _shape *shape = shape_new();
// shape_area(shape, shape);
// shape_draw(shape, shape);
printf("----- copper_cash -----\n");
struct _copper_cash *cc = copper_cash_new(2, 2, 4);
shape_area(cc, cc->shape);
shape_draw(cc, cc->shape);
printf("----- [2] copper_cash -----\n");
rect_area(cc, cc->rect);
rect_draw(cc, cc->rect);
circle_area(cc, cc->circle);
circle_draw(cc, cc->circle);
return 0;
}