使用C语言实现面向对象程序设计
学过c语言的人都直到c语言学习语法简单但精通起来比较难难点在于c语言太“低级”它面向的是机器的一个执行过程不像C、java这种高级语言在语法层级就支持面向对象的抽象。所以往往初学者在使用c语言编程时稍微遇到复杂一点的功能就会出现各种全局变量标志位满天飞的情况代码维护性和阅读性变得很差过个一两年再去阅读自己以前写的代码遇到没写注释的全局变量可能都得靠猜。但其实这也是c语言区别于其他语言最优秀的地方因为语法简单没有语法上的各种约束和限制它是最容易上手的语言其他面向对象的语言你首先得有一个对事物的抽象能力才能把程序的结构设计好。同时它具有别的编程语言不能比拟的最优秀的执行效率因此在资源受限的场景下比如嵌入式单片机等c语言是一个不错的选择。但并不意味着c语言只能处理这种偏“底层”的应用场景使用c语言同样能实现面向对象的程序设计。并且它在某些方面还优于其他高级语言。下面结合我的理解讲一讲如何使用c语言实现面向对象的程序设计。面向对象核心特性1. 封装通过结构体与函数指针捆绑数据与操作例如封装一个对象用于描述系统电源特性包括电压、电流、充放电状态等同时定义这个对象的操作方法电源 {电压电流电源状态剩余电量操作方法获取电压获取电流获取电源状态获取剩余电量设置电源状态}那么使用c语言如何来实现呢我们可以在结构体中定义对象的属性然后使用函数指针定义这个对象的操作方法如下power.h头文件定义如下#ifndef POWER_H #define POWER_H #include stdlib.h #include stdint.h #include stdbool.h #include string.h #define GET_POWER(obj) ((Power *)obj) // 类声明 typedef struct _Power Power; typedef struct _PowerFun PowerFun; // 类成员函数结构 struct _PowerFun { void (*destroy)(Power* self); uint16_t (*getVoltage)(Power* self);//获取电压; uint16_t (*getCurrent)(Power* self);//获取电流; uint16_t (*getPowerState)(Power* self);//获取电源状态; uint16_t (*getPowerLevel)(Power* self);//获取剩余电量; void (*setPowerState)(Power* self, uint8_t state);//设置电源状态; }; // 类结构 struct _Power { const PowerFun* fun; // TODO: 添加数据成员 uint16_t voltage; //电压 uint16_t current; //电流 uint16_t power_state;//电源状态 uint16_t power_level;//剩余电量 }; // 构造函数声明 Power* power_create(); void power_init(Power* self); // 析构函数声明 void power_deinit(Power* self); #endif // POWER_Hpower.c具体实现如下#include power.h #include stdio.h static uint16_t power_getCurrent(Power* self); static uint16_t power_getPowerState(Power* self); static uint16_t power_getPowerLevel(Power* self); static void power_setPowerState(Power* self, uint8_t state); static uint16_t power_getVoltage(Power* self); // 析构函数声明 static void power_destroy(Power* self); // TODO: 初始化数据成员 static const PowerFun power_fun { .destroy power_destroy, .getVoltage power_getVoltage, .getCurrent power_getCurrent, .getPowerState power_getPowerState, .getPowerLevel power_getPowerLevel, .setPowerState power_setPowerState, }; // 构造函数实现 Power* power_create() { Power* obj (Power*)malloc(sizeof(Power)); if (obj) { memset(obj, 0, sizeof(Power)); power_init(obj); } return obj; } void power_init(Power* self) { self-fun (power_fun); // TODO: 初始化数据成员 } void power_deinit(Power* self) { // TODO: 数据成员申请资源释放 } // 析构函数实现 static void power_destroy(Power* self) { if (self ! NULL) { power_deinit(self); free(self); } } // getVoltage method static uint16_t power_getVoltage(Power* self) { if (self ! NULL) { return self-voltage; } return 0; } // getCurrent method static uint16_t power_getCurrent(Power* self) { if (self ! NULL) { return self-current; } return 0; } // getPowerState method static uint16_t power_getPowerState(Power* self) { if (self ! NULL) { return self-power_state; } return 0; } // getPowerLevel method static uint16_t power_getPowerLevel(Power* self) { if (self ! NULL) { return self-power_level; } return 0; } // setPowerState method static void power_setPowerState(Power* self, uint8_t state) { if (self ! NULL) { self-power_state state; } }使用方法很简单Power* systempower power_create(); systempower-fun-getVoltage(systempower);//获取电压; systempower-fun-getCurrent(systempower);//获取电流; systempower-fun-getPowerState(systempower);//获取电源状态; systempower-fun-getPowerLevel(systempower);//获取剩余电量; systempower-fun-setPowerState(systempower, 11);//设置电源状态;2. 继承所谓继承就是基于一个已有的类父类来创建一个新的类子类。子类会自动获得父类的属性和方法并且可以在此基础上进行扩展增加自己特有的属性和方法或者修改父类的方法。那么在c语言中如何实现继承呢我们可以通过结构体嵌套实现这种继承的层次关系回到上面的例子再次定义一个对象chargepower继承自上面定义的power对象这个对象新增充电和放电操作方法并且新增了充电电流、电压和放电电流、电压、充满剩余时间等属性。充放电电源继承电源 {充电电压充电电流放电电压放电电流充满剩余时间操作方法充电放电}chargepower.h定义如下#ifndef CHARGEPOWER_H #define CHARGEPOWER_H #include stdint.h #include stdbool.h #include Power.h #define GET_CHARGEPOWER_VTABLE(obj) GET_POWER_VTABLE(obj) //(*(ChargepowerVTable **)obj) #define GET_CHARGEPOWER(obj) ((Chargepower *)obj) // 派生类声明 typedef struct _Chargepower Chargepower; typedef struct _ChargepowerFun ChargepowerFun; // 类成员函数结构 struct _ChargepowerFun { void (*destroy)(Chargepower* self); void (*charge)(Chargepower* self);//充电 void (*discharge)(Chargepower* self);//放电 }; struct _Chargepower { Power base; // 基类作为第一个成员 const ChargepowerFun* fun; // TODO: 添加派生类特有的数据成员 uint16_t charge_voltage; //充电电压 uint16_t charge_current; //充电电流 uint16_t discharge_voltage;//放电电压 uint16_t discharge_current;//放电电流 uint16_t charge_time;//充电剩余时间 }; // 构造函数声明 Chargepower* chargepower_create(); void chargepower_init(Chargepower* self); // 析构函数声明 void chargepower_deinit(Chargepower* self); #endif // CHARGEPOWER_Hchargepower.c定义如下#include chargepower.h #include stdio.h #include stdlib.h static void chargepower_discharge(Chargepower* self); static void chargepower_charge(Chargepower* self); // 析构函数声明 static void chargepower_destroy(Chargepower* self); // TODO: 初始化数据成员 static const ChargepowerFun chargepower_fun { .destroy chargepower_destroy, .charge chargepower_charge, .discharge chargepower_discharge, }; // 构造函数实现 Chargepower* chargepower_create() { Chargepower* obj (Chargepower*)malloc(sizeof(Chargepower)); if (obj) { memset(obj, 0, sizeof(Chargepower)); chargepower_init(obj); } return obj; } void chargepower_init(Chargepower* self) { // 初始化基类部分 power_init(self-base); self-fun (chargepower_fun); // TODO: 初始化派生类特有成员 } void chargepower_deinit(Chargepower* self) { power_deinit(GET_POWER(self)); // TODO: 数据成员申请资源释放 } // 析构函数实现 static void chargepower_destroy(Chargepower* self) { if (self ! NULL) { chargepower_deinit(self); free(self); } } // charge method static void chargepower_charge(Chargepower* self) { // TODO: add charge method } // discharge method static void chargepower_discharge(Chargepower* self) { // TODO: add discharge method }如何使用chargepower对象中的父类和自身的方法呢使用下面的方式即可Chargepower *chargepower chargepower_create(); //调用自身方法 chargepower-fun-charge(chargepower); //充电 chargepower-fun-discharge(chargepower);//放电 //调用父类方法 GET_POWER(chargepower)-fun-getVoltage(GET_POWER(chargepower));//获取电压; GET_POWER(chargepower)-fun-getCurrent(GET_POWER(chargepower));//获取电流; GET_POWER(chargepower)-fun-getPowerState(GET_POWER(chargepower));//获取电源状态; GET_POWER(chargepower)-fun-getPowerLevel(GET_POWER(chargepower));//获取剩余电量; GET_POWER(chargepower)-fun-setPowerState(GET_POWER(chargepower), 12);//设置电源状态;3. 多态多态的字面意思是多种形态。在面向对象编程中它指的是同一个行为方法在不同的对象上会表现出不同的实现方式。简单来说就是使用统一的接口来操作不同类型的对象而这些对象会根据自己的特性做出不同的响应。那么在c语言中如何来实现多态呢我们可以利用函数指针动态绑定不同的操作函数来实现多态例如可以在定义对象的时候定义一个虚函数表这个虚函数表指针可以由继承的对象赋值不同的继承对象可以赋值不同操作函数从而实现多态虚函数表{虚函数指针}电源 {虚函数表电压电流电源状态剩余电量操作方法获取电压获取电流获取电源状态获取剩余电量设置电源状态}示例代码定义virtualpower.h如下#ifndef VIRTUALPOWER_H #define VIRTUALPOWER_H #include stdlib.h #include stdint.h #include stdbool.h #include string.h #define GET_VIRTUALPOWER_VTABLE(obj) (*(VirtualpowerVTable **)obj) #define getMaxCurrent_override(func_name) static uint16_t func_name(Virtualpower* self) #define def_getMaxCurrent(obj) (GET_VIRTUALPOWER_VTABLE(obj)-getMaxCurrent) #define virtual_getMaxCurrent(obj, ...) def_getMaxCurrent(obj)(obj, ##__VA_ARGS__) #define GET_VIRTUALPOWER(obj) ((Virtualpower *)obj) // 类声明 typedef struct _Virtualpower Virtualpower; typedef struct _VirtualpowerFun VirtualpowerFun; typedef struct _VirtualpowerVTable VirtualpowerVTable; // 虚函数表结构 typedef struct _VirtualpowerVTable { // TODO : 添加其他虚函数 uint16_t (*getMaxCurrent)(Virtualpower* self);//虚函数由继承类来实现定义 }; // 类成员函数结构 struct _VirtualpowerFun { void (*destroy)(Virtualpower* self); uint16_t (*getVoltage)(Virtualpower* self); uint16_t (*getCurrent)(Virtualpower* self); uint16_t (*getPowerState)(Virtualpower* self); uint16_t (*getPowerLevel)(Virtualpower* self); void (*setPowerState)(Virtualpower* self, uint8_t state); }; // 类结构 struct _Virtualpower { VirtualpowerVTable* vtable; const VirtualpowerFun* fun; // TODO: 添加数据成员 uint16_t voltage; //电压 uint16_t current; //电流 uint16_t power_state;//电源状态 uint16_t power_level;//剩余电量 }; // 构造函数声明 Virtualpower* virtualpower_create(); void virtualpower_init(Virtualpower* self); // 析构函数声明 void virtualpower_deinit(Virtualpower* self); #endif // VIRTUALPOWER_H定义virtualpower.c如下#include virtualpower.h #include stdio.h static uint16_t virtualpower_getVoltage(Virtualpower* self); static uint16_t virtualpower_getCurrent(Virtualpower* self); static uint16_t virtualpower_getPowerState(Virtualpower* self); static uint16_t virtualpower_getPowerLevel(Virtualpower* self); static void virtualpower_setPowerState(Virtualpower* self, uint8_t state); // 析构函数声明 static void virtualpower_destroy(Virtualpower* self); // TODO: 初始化数据成员 static const VirtualpowerFun virtualpower_fun { .destroy virtualpower_destroy, .getVoltage virtualpower_getVoltage, .getCurrent virtualpower_getCurrent, .getPowerState virtualpower_getPowerState, .getPowerLevel virtualpower_getPowerLevel, .setPowerState virtualpower_setPowerState, }; // 构造函数实现 Virtualpower* virtualpower_create() { Virtualpower* obj (Virtualpower*)malloc(sizeof(Virtualpower)); if (obj) { memset(obj, 0, sizeof(Virtualpower)); virtualpower_init(obj); } return obj; } void virtualpower_init(Virtualpower* self) { if (self-vtable NULL) { self-vtable (VirtualpowerVTable *) malloc(sizeof(VirtualpowerVTable)); memset(self-vtable , 0, sizeof(VirtualpowerVTable)); } self-fun (virtualpower_fun); // TODO: 初始化数据成员 } void virtualpower_deinit(Virtualpower* self) { if (self-vtable ! NULL) { free(self-vtable); self-vtable NULL; } // TODO: 数据成员申请资源释放 } // 析构函数实现 static void virtualpower_destroy(Virtualpower* self) { if (self ! NULL) { virtualpower_deinit(self); free(self); } } // getVoltage method static uint16_t virtualpower_getVoltage(Virtualpower* self) { // TODO: add getVoltage method return 0; } // getCurrent method static uint16_t virtualpower_getCurrent(Virtualpower* self) { // TODO: add getCurrent method return 0; } // getPowerState method static uint16_t virtualpower_getPowerState(Virtualpower* self) { // TODO: add getPowerState method return 0; } // getPowerLevel method static uint16_t virtualpower_getPowerLevel(Virtualpower* self) { // TODO: add getPowerLevel method return 0; } // setPowerState method static void virtualpower_setPowerState(Virtualpower* self, uint8_t state) { // TODO: add setPowerState method }那么当有子类继承Virtualpower这个父类时可以实现这个虚函数GET_VIRTUALPOWER_VTABLE(obj)-getMaxCurrent xxxx例如定义sonpower子类继承自virtualpowersonpower.h实现#ifndef SONPOWER_H #define SONPOWER_H #include stdint.h #include stdbool.h #include Virtualpower.h #define GET_SONPOWER_VTABLE(obj) GET_VIRTUALPOWER_VTABLE(obj) //(*(SonpowerVTable **)obj) #define GET_SONPOWER(obj) ((Sonpower *)obj) // 派生类声明 typedef struct _Sonpower Sonpower; typedef struct _SonpowerFun SonpowerFun; // 类成员函数结构 struct _SonpowerFun { void (*destroy)(Sonpower* self); }; struct _Sonpower { Virtualpower base; // 基类作为第一个成员 const SonpowerFun* fun; // TODO: 添加派生类特有的数据成员 }; // 构造函数声明 Sonpower* sonpower_create(); void sonpower_init(Sonpower* self); // 析构函数声明 void sonpower_deinit(Sonpower* self); #endif // SONPOWER_Hsonpower.c实现#include sonpower.h #include stdio.h #include stdlib.h getMaxCurrent_override(sonpower_getMaxCurrent_impl); // 析构函数声明 static void sonpower_destroy(Sonpower* self); // TODO: 初始化数据成员 static const SonpowerFun sonpower_fun { .destroy sonpower_destroy, }; // 构造函数实现 Sonpower* sonpower_create() { Sonpower* obj (Sonpower*)malloc(sizeof(Sonpower)); if (obj) { memset(obj, 0, sizeof(Sonpower)); sonpower_init(obj); } return obj; } void sonpower_init(Sonpower* self) { // 初始化基类部分 virtualpower_init(self-base); self-fun (sonpower_fun); // TODO: 初始化派生类特有成员 def_getMaxCurrent(self) sonpower_getMaxCurrent_impl; } void sonpower_deinit(Sonpower* self) { virtualpower_deinit(GET_VIRTUALPOWER(self)); // TODO: 数据成员申请资源释放 } // 析构函数实现 static void sonpower_destroy(Sonpower* self) { if (self ! NULL) { sonpower_deinit(self); free(self); } } // getMaxCurrent method getMaxCurrent_override(sonpower_getMaxCurrent_impl) { // TODO: add getMaxCurrent method Sonpower *sonpower (Sonpower *)self; //params return 0; }如何使用这个虚函数呢也很简单Sonpower *sonpower sonpower_create(); uint16_t maxcurrent virtual_getMaxCurrent(GET_VIRTUALPOWER(systempower));通过上面给出的例子可以实现在c语言下使用面向对象编程。但是看起来代码比较繁杂很多代码看起来都是一样的模式能不能做一个插件呢将这些重复的地方通过插件直接自动生成了这样就不需要一行行手敲了当然可以下次再聊如果使用vscode开发有便利工具插件VSCode面向对象c插件开源实现