cmake_demo/main.c

213 lines
3.9 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 void (*area)(void *self);
VIRTUAL void (*draw)(void *self);
};
void virtual_area(void *self)
{
ASSERT_CALL_VIRTUAL_METHOD();
}
void virtual_draw(void *self)
{
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;
};
void shape_area(void *self)
{
struct _shape *this = (struct _shape *)self;
this->vtb->area(self);
}
void shape_draw(void *self)
{
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 = calloc(1, sizeof(struct _shape));
if(shape == NULL)
{
return NULL;
}
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)
{
if (self != NULL)
{
free(self);
}
}
#endif
struct _rect
{
// super
struct _shape shape;
// attribute
double width, height;
// method
// void (*area)(void *self);
// void (*draw)(void *self);
};
void rect_area(struct _rect *self)
{
printf("rect area = %0.2f\n", self->width * self->height);
}
void rect_draw(struct _rect *self)
{
printf("rect draw\n");
}
struct _rect *rect_new(double width, double height)
{
struct _rect *rect = calloc(1, sizeof(struct _rect));
if (rect == NULL)
{
return NULL;
}
rect->width = width;
rect->height = height;
static struct _virtual_table vtb = {
.area = (void (*)(void *self))rect_area,
.draw = (void (*)(void *self))rect_draw
};
SUPER(rect)->vtb = &vtb;
return rect;
}
struct _circle
{
// super
struct _shape shape;
// attribute
double radius;
// method
// void (*area)(void *self);
// void (*draw)(void *self);
};
void circle_area(struct _circle *self)
{
printf("circle area = %0.2f\n", 3.14 * self->radius * self->radius);
}
void circle_draw(struct _circle *self)
{
printf("circle draw\n");
}
struct _circle *circle_new(double radius)
{
struct _circle *circle = calloc(1, sizeof(struct _circle));
if (circle == NULL)
{
return NULL;
}
circle->radius = radius;
static struct _virtual_table vtb = {
.area = (void (*)(void *self))circle_area,
.draw = (void (*)(void *self))circle_draw,
};
SUPER(circle)->vtb = &vtb;
return circle;
}
int main(int argc, char *argv[])
{
struct _rect *rect = rect_new(4, 5);
rect_area(rect);
rect_draw(rect);
struct _circle *circle = circle_new(3);
circle_area(circle);
circle_draw(circle);
printf("------------------------------\n");
shape_area(rect);
shape_area(circle);
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;
}