一种C语言多态的实现示例

1. 抽象的shape类

/*************************************************************************
	> File Name: shape.h
	> Author: XXDK
	> Email: v.manstein@qq.com 
	> Created Time: Thu 12 Sep 2019 01:59:14 PM CST
 ************************************************************************/

#ifndef _SHAPE_H
#define _SHAPE_H

#include <stdint.h>

#ifdef __cplusplus
extern "C" {
#endif

struct shape_vtbl;
struct shape {
	const struct shape_vtbl* vptr; ///< virtual table pointer
	int x; ///< x coordinate of shape's position
	int y; ///< y coordinate of shape's position
};

///< virtual method table 
struct shape_vtbl {
	uint32_t (*area)(const struct shape* const pthis);
	void (*draw)(const struct shape* const pthis);
};

extern void shape_static_ctor(struct shape* const pthis, int x, int y);
extern void shape_moveby(struct shape* const pthis, int dx, int dy);
extern int shape_getx(struct shape const *pthis);
extern int shape_gety(struct shape const *pthis);
extern struct shape const* largest_shape(const struct shape* shapes[], uint32_t nshapes);
extern void draw_all_shapes(const struct shape* shapes[], uint32_t nshapes);

///< virtual method
extern uint32_t shape_area(const struct shape* const pthis);
extern void shape_draw(const struct shape* const pthis);

#ifdef __cplusplus
}
#endif

#endif // _SHAPE_H

/*************************************************************************
	> File Name: shape.c
	> Author: XXDK
	> Email: v.manstein@qq.com 
	> Created Time: Thu 12 Sep 2019 02:31:42 PM CST
 ************************************************************************/

#include <stdio.h>
#include "shape.h" 

///< virtual base class virtual method: do nothing!
//static inline void shape_draw_(const struct shape* const pthis);
//static inline uint32_t shape_area_(const struct shape* const pthis);

void shape_static_ctor(struct shape* const pthis, int x, int y)
{
	static struct shape_vtbl vtbl = {
		.area = NULL /*shape_area_*/,
		.draw = NULL /*shape_draw_*/,
	};
	pthis->vptr = &vtbl;
	pthis->x = x;
	pthis->y = y;
}

void shape_moveby(struct shape* const pthis, int dx, int dy)
{
	pthis->x += dx;
	pthis->y += dy;
}

int shape_getx(struct shape const *pthis)
{
	return pthis->x;
}

int shape_gety(struct shape const *pthis)
{
	return pthis->y;
}

///< virtual method
inline uint32_t shape_area(const struct shape* const pthis)
{
	return (*pthis->vptr->area)(pthis);
}

///< virtual method
inline void shape_draw(const struct shape* const pthis)
{
	(*pthis->vptr->draw)(pthis);
}

/*
static inline uint32_t shape_area_(const struct shape* const pthis)
{
	assert(0);
	return 0U;
}

static inline void shape_draw_(const struct shape* const pthis)
{
	assert(0);
}
*/

struct shape const* largest_shape(const struct shape* shapes[], uint32_t nshapes)
{
	const struct shape* s = NULL; 
	uint32_t max = 0U;
	
	for (uint32_t i = 0U; i < nshapes; i++) {
		uint32_t area = shape_area(shapes[i]);
		if (area > max) 
			max = area;
		s = shapes[i];
	}

	return s;
}

void draw_all_shapes(const struct shape* shapes[], uint32_t nshapes)
{
	for (uint32_t i = 0U; i < nshapes; i++) {
		shape_draw(shapes[i]);
	}
}



2. 派生类rectangle

/*************************************************************************
	> File Name: rectangle.h
	> Author: XXDK
	> Email: v.manstein@qq.com 
	> Created Time: Thu 12 Sep 2019 02:15:31 PM CST
 ************************************************************************/

#ifndef _RECTANGLE_H
#define _RECTANGLE_H

#include <stdint.h>
#include "shape.h"

#ifdef __cplusplus
extern "C" {
#endif

struct rectangle {
	struct shape super;	
	uint32_t width;	
	uint32_t height;	
};

extern void rectangle_static_ctor(struct rectangle* const pthis, int x, int y, uint32_t w, uint32_t h);
extern struct rectangle* rectangle_dynamic_ctor(int x, int y, uint32_t w, uint32_t h);
extern void rectangle_dynamic_dtor(struct rectangle** pthis);
///< virtual method override
extern void rectangle_draw_override(const struct shape* const pthis);
extern uint32_t rectangle_area_override(const struct shape* const pthis);

#ifdef __cplusplus
}
#endif

#endif // _RECTANGLE_H

/*************************************************************************
	> File Name: rectangle.c
	> Author: XXDK
	> Email: v.manstein@qq.com 
	> Created Time: Thu 12 Sep 2019 02:33:35 PM CST
 ************************************************************************/

#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>
#include "rectangle.h"

void rectangle_static_ctor(struct rectangle* const pthis, int x, int y, uint32_t w, uint32_t h)
{
	static struct shape_vtbl const vtbl = {
		.draw = rectangle_draw_override,
		.area = rectangle_area_override,
	};
	shape_static_ctor(&pthis->super, x, y);
	pthis->super.vptr = &vtbl;
	pthis->width = w;
	pthis->height = h;
}

struct rectangle* rectangle_dynamic_ctor(int x, int y, uint32_t w, uint32_t h)
{
	struct rectangle* pthis = malloc(sizeof(struct rectangle));
	rectangle_static_ctor(pthis, x, y, w, h);

	return pthis;
}

void rectangle_dynamic_dtor(struct rectangle** pthis)
{
	free(*pthis);
}

void rectangle_draw_override(const struct shape* const pthis)
{
	const struct rectangle* const pthis_ = (const struct rectangle*)pthis;
	printf("rectangle draw: x = %d, y = %d, width = %d, height = %d\n", 
			pthis->x, pthis->y, pthis_->width, pthis_->height);
}

uint32_t rectangle_area_override(const struct shape* const pthis)
{
	const struct rectangle* const pthis_ = (const struct rectangle*)pthis;
	return pthis_->width * pthis_->height;
}


3. 派生类circle

/*************************************************************************
	> File Name: circle.h
	> Author: XXDK
	> Email: v.manstein@qq.com 
	> Created Time: Thu 12 Sep 2019 02:21:04 PM CST
 ************************************************************************/

#ifndef _CIRCLE_H
#define _CIRCLE_H

#include <stdint.h>
#include "shape.h"

#ifdef __cplusplus
extern "C" {
#endif
struct circle {
	struct shape super;	
	uint32_t radius;	
};

extern void circle_static_ctor(struct circle* const pthis, int x, int y, uint32_t r);
extern struct circle* circle_dynamic_ctor(int x, int y, uint32_t r);
extern void circle_dynamic_dtor(struct circle** pthis);
///< virtual method override
extern void circle_draw_override(const struct shape* const pthis);
extern uint32_t circle_area_override(const struct shape* const pthis);

#ifdef __cplusplus
}
#endif

#endif // _CIRCLE_H

/*************************************************************************
	> File Name: circle.c
	> Author: XXDK
	> Email: v.manstein@qq.com 
	> Created Time: Thu 12 Sep 2019 02:34:39 PM CST
 ************************************************************************/

#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>
#include "circle.h"

void circle_static_ctor(struct circle* const pthis, int x, int y, uint32_t r)
{
	static struct shape_vtbl const vtbl = {
		.draw = circle_draw_override,
		.area = circle_area_override,
	};
	shape_static_ctor(&pthis->super, x, y);
	pthis->super.vptr = &vtbl;
	pthis->radius = r;
}

struct circle* circle_dynamic_ctor(int x, int y, uint32_t r)
{
	struct circle* pthis = malloc(sizeof(struct circle));
	circle_static_ctor(pthis, x, y, r);

	return pthis;
}

void circle_dynamic_dtor(struct circle** pthis)
{
	free(*pthis);
}

void circle_draw_override(const struct shape* const pthis)
{
	const struct circle* const pthis_ = (const struct circle*)pthis;
	printf("circle draw: x = %d, y = %d, radius = %d\n", 
			pthis->x, pthis->y, pthis_->radius);
}

uint32_t circle_area_override(const struct shape* const pthis)
{
	const struct circle* const pthis_ = (const struct circle*)pthis;
	return (uint32_t)(3.1415926 * pthis_->radius * pthis_->radius);
}

4. 测试用例

/*************************************************************************
	> File Name: test_oopc.c
	> Author: XXDK
	> Email: v.manstein@qq.com 
	> Created Time: Wed 11 Sep 2019 05:30:38 PM PDT
 ************************************************************************/

#include<stdio.h>
#include<stdint.h>
#include<assert.h>
#include<stdlib.h>
#include"shape.h"
#include"rectangle.h"
#include"circle.h"

int main()
{
	struct rectangle r1;	
	rectangle_static_ctor(&r1, 20, 20, 20, 20);
	struct rectangle* r2 = rectangle_dynamic_ctor(40, 40, 40, 40);

	struct circle c1;	
	circle_static_ctor(&c1, 60, 60, 20);
	struct circle* c2 = circle_dynamic_ctor(80, 80, 40);

	rectangle_draw_override((struct shape*)&r1); ///< call override virtual method
	rectangle_draw_override((struct shape*)r2);

	circle_draw_override((struct shape*)&c1);
	circle_draw_override((struct shape*)c2);

	//const struct shape* sa[] = {&r1.super, &r2.super, &r3->super};
	const struct shape* sa[] = {(struct shape*)&r1, (struct shape*)r2,
	                            (struct shape*)&c1, (struct shape*)c2};
	struct shape const *s = largest_shape(sa, sizeof(sa)/sizeof(sa[0]));
	printf("largest shape: x = %d, y = %d, area = %d\n", shape_getx(s), shape_gety(s), shape_area(s));

	rectangle_dynamic_dtor(&r2);
	circle_dynamic_dtor(&c2);

	return 0;
}

5. 编译

# set envrionment
CC=gcc
CC_FLAGS=-D_FILELINE
SRCS=$(wildcard *.c */*.c)

#set inc and lib
INCS=-I .
LIBS=-lpthread -L.

TARGET=test_oopc
OBJS=$(patsubst %.c, %.o, $(SRCS))

all:$(TARGET)
$(TARGET):$(OBJS)
	$(CC) -o $@ $^ $(LIBS)

%.o:%.c
	$(CC) $(CC_FLAGS) $(INCS) $(LIBS) -c -g $< -o $@

.PHONY: install clean
install:

clean:
	rm $(TARGET) $(OBJS)
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值