關注+星標公眾號,不錯過精彩內容

編排 |?strongerHuang
為什么要用C語言實現面向對象
具備條件
封裝
// Shape 的屬性typedef struct {int16_t x;int16_t y;} Shape;// Shape 的操作函數,接口函數void Shape_ctor(Shape * const me, int16_t x, int16_t y);void Shape_moveBy(Shape * const me, int16_t dx, int16_t dy);int16_t Shape_getX(Shape const * const me);int16_t Shape_getY(Shape const * const me);
// 構造函數void Shape_ctor(Shape * const me, int16_t x, int16_t y){me->x = x;me->y = y;}void Shape_moveBy(Shape * const me, int16_t dx, int16_t dy){me->x += dx;me->y += dy;}// 獲取屬性值函數int16_t Shape_getX(Shape const * const me){return me->x;}int16_t Shape_getY(Shape const * const me){return me->y;}
#include "shape.h" /* Shape class interface */#include/* for printf() */ int main(){Shape s1, s2; /* multiple instances of Shape */Shape_ctor(&s1, 0, 1);Shape_ctor(&s2, -1, 2);printf("Shape s1(x=%d,y=%d)\n", Shape_getX(&s1), Shape_getY(&s1));printf("Shape s2(x=%d,y=%d)\n", Shape_getX(&s2), Shape_getY(&s2));Shape_moveBy(&s1, 2, -4);Shape_moveBy(&s2, 1, -2);printf("Shape s1(x=%d,y=%d)\n", Shape_getX(&s1), Shape_getY(&s1));printf("Shape s2(x=%d,y=%d)\n", Shape_getX(&s2), Shape_getY(&s2));return 0;}
Shape s1(x=0,y=1)Shape s2(x=-1,y=2)Shape s1(x=2,y=-3)Shape s2(x=0,y=0)
繼承
// 矩形的屬性typedef struct {Shape super; // 繼承 Shape// 自己的屬性uint16_t width;uint16_t height;} Rectangle;// 構造函數void Rectangle_ctor(Rectangle * const me, int16_t x, int16_t y,uint16_t width, uint16_t height);
// 構造函數void Rectangle_ctor(Rectangle * const me, int16_t x, int16_t y,uint16_t width, uint16_t height){/* first call superclass’ ctor */Shape_ctor(&me->super, x, y);/* next, you initialize the attributes added by this subclass... */me->width = width;me->height = height;}

#include "rect.h"#includeint main(){Rectangle r1, r2;// 實例化對象Rectangle_ctor(&r1, 0, 2, 10, 15);Rectangle_ctor(&r2, -1, 3, 5, 8);printf("Rect r1(x=%d,y=%d,width=%d,height=%d)\n",Shape_getX(&r1.super), Shape_getY(&r1.super),r1.width, r1.height);printf("Rect r2(x=%d,y=%d,width=%d,height=%d)\n",Shape_getX(&r2.super), Shape_getY(&r2.super),r2.width, r2.height);// 注意,這里有兩種方式,一是強轉類型,二是直接使用成員地址Shape_moveBy((Shape *)&r1, -2, 3);Shape_moveBy(&r2.super, 2, -1);printf("Rect r1(x=%d,y=%d,width=%d,height=%d)\n",Shape_getX(&r1.super), Shape_getY(&r1.super),r1.width, r1.height);printf("Rect r2(x=%d,y=%d,width=%d,height=%d)\n",Shape_getX(&r2.super), Shape_getY(&r2.super),r2.width, r2.height);return 0;}
Rect r1(x=0,y=2,width=10,height=15)Rect r2(x=-1,y=3,width=5,height=8)Rect r1(x=-2,y=5,width=10,height=15)Rect r2(x=1,y=2,width=5,height=8)
多態
struct ShapeVtbl;// Shape 的屬性typedef struct {struct ShapeVtbl const *vptr;int16_t x;int16_t y;} Shape;// Shape 的虛表struct ShapeVtbl {uint32_t (*area)(Shape const * const me);void (*draw)(Shape const * const me);};// Shape 的操作函數,接口函數void Shape_ctor(Shape * const me, int16_t x, int16_t y);void Shape_moveBy(Shape * const me, int16_t dx, int16_t dy);int16_t Shape_getX(Shape const * const me);int16_t Shape_getY(Shape const * const me);static inline uint32_t Shape_area(Shape const * const me){return (*me->vptr->area)(me);}static inline void Shape_draw(Shape const * const me){(*me->vptr->draw)(me);}Shape const *largestShape(Shape const *shapes[], uint32_t nShapes);void drawAllShapes(Shape const *shapes[], uint32_t nShapes);

// Shape 的虛函數static uint32_t Shape_area_(Shape const * const me);static void Shape_draw_(Shape const * const me);// 構造函數void Shape_ctor(Shape * const me, int16_t x, int16_t y){// Shape 類的虛表static struct ShapeVtbl const vtbl ={&Shape_area_,&Shape_draw_};me->vptr = &vtbl;me->x = x;me->y = y;}void Shape_moveBy(Shape * const me, int16_t dx, int16_t dy){me->x += dx;me->y += dy;}int16_t Shape_getX(Shape const * const me){return me->x;}int16_t Shape_getY(Shape const * const me){return me->y;}// Shape 類的虛函數實現static uint32_t Shape_area_(Shape const * const me){assert(0); // 類似純虛函數return 0U; // 避免警告}static void Shape_draw_(Shape const * const me){assert(0); // 純虛函數不能被調用}Shape const *largestShape(Shape const *shapes[], uint32_t nShapes){Shape const *s = (Shape *)0;uint32_t max = 0U;uint32_t i;for (i = 0U; i < nShapes; ++i){uint32_t area = Shape_area(shapes[i]);// 虛函數調用if (area > max){max = area;s = shapes[i];}}return s;}void drawAllShapes(Shape const *shapes[], uint32_t nShapes){uint32_t i;for (i = 0U; i < nShapes; ++i){Shape_draw(shapes[i]); // 虛函數調用}}
// Rectangle 虛函數static uint32_t Rectangle_area_(Shape const * const me);static void Rectangle_draw_(Shape const * const me);// 構造函數void Rectangle_ctor(Rectangle * const me, int16_t x, int16_t y,uint16_t width, uint16_t height){static struct ShapeVtbl const vtbl ={&Rectangle_area_,&Rectangle_draw_};Shape_ctor(&me->super, x, y); // 調用基類的構造函數me->super.vptr = &vtbl; // 重載 vptrme->width = width;me->height = height;}// Rectangle's 虛函數實現static uint32_t Rectangle_area_(Shape const * const me){Rectangle const * const me_ = (Rectangle const *)me; //顯示的轉換return (uint32_t)me_->width * (uint32_t)me_->height;}static void Rectangle_draw_(Shape const * const me){Rectangle const * const me_ = (Rectangle const *)me; //顯示的轉換printf("Rectangle_draw_(x=%d,y=%d,width=%d,height=%d)\n",Shape_getX(me), Shape_getY(me), me_->width, me_->height);}
uint32_t Shape_area(Shape const * const me){return (*me->vptr->area)(me);}
static inline uint32_t Shape_area(Shape const * const me){return (*me->vptr->area)(me);}

int main(){Rectangle r1, r2;Circle c1, c2;Shape const *shapes[] ={&c1.super,&r2.super,&c2.super,&r1.super};Shape const *s;// 實例化矩形對象Rectangle_ctor(&r1, 0, 2, 10, 15);Rectangle_ctor(&r2, -1, 3, 5, 8);// 實例化圓形對象Circle_ctor(&c1, 1, -2, 12);Circle_ctor(&c2, 1, -3, 6);s = largestShape(shapes, sizeof(shapes)/sizeof(shapes[0]));printf("largetsShape s(x=%d,y=%d)\n", Shape_getX(s), Shape_getY(s));drawAllShapes(shapes, sizeof(shapes)/sizeof(shapes[0]));return 0;}
largetsShape s(x=1,y=-2)Circle_draw_(x=1,y=-2,rad=12)Rectangle_draw_(x=-1,y=3,width=5,height=8)Circle_draw_(x=1,y=-3,rad=6)Rectangle_draw_(x=0,y=2,width=10,height=15)
總結
參考素材: https://blog.csdn.net/onlyshi/article/details/81672279
------------?END?------------

●專欄《嵌入式開發》
●專欄《Keil教程》
●嵌入式專欄精選教程
關注公眾號回復“加群”按規則加入技術交流群,回復“1024”查看更多內容。