面向对象 - 封装
最近在招聘网站上看了不少关于MCU或者嵌入式相关的招聘信息,发现很多公司对应聘人员有个要求就是精通c/c++。精通c可以理解,毕竟靠这个吃饭的,但是为什么还要熟悉甚至要精通c++呢?我们MCU或者嵌入式软件更多的不是使用c吗?想想也是,虽然很多时候我们编程并不用c++,但是c++中的编程思想确实是值得c程序员学习的,比如c++中的核心概念-封装,继承,多态。
那么,什么是c++中的封装,继承,多态呢?做为c程序员,我们可以向c++学习什么呢?
众多周知,c++是一门面向对象语言,一个对象包括了这个对象可以做的事(行为)以及要做这些事所用到的数据(属性)。对于对象的使用者而言,对象就是一个独立的封闭的个体,他能帮我们完成一些并不需要我们知道细节的事情。比如公司的业务向研发提出某种技术需求需要,业务并不需要知道怎么去研发这个技术,他只需要知道找谁能解决这个问题就可以。这里你有可能会说了,对象中包括了行为与属性,那这些行为与属性实现本身不也是类似于c一样面向过程的吗?说的没错,但是别忘了面向对象除了封装以外还有其核心思想继承与多态。
在c中如何封装可以怎么实现呢?
(1)使用.c以及.h文件作为封装边界。把一组相关操作放在.c文件,对外开放的变量以及函数则在.h文件中声明。比如下面一个操作LED亮灭的例子。
led.h文件中的声明
#ifndef _LED_
#define _LED_
/*对外开放*/
typedef enum
{
LED1,
LED2,
LED3
}led_num_t;
/*对外开放*/
extern led_on(led_num_t num);
extern led_off(led_num_t num);
#endif
相关操作的实现则定义在led.c文件中
#include "led.h"
void led_on(led_num_t num)
{
}
void led_off(len_num_t num)
{
}
要注意的是由于led.c对外是封闭的,所以要尽量避免全局变量或者其他模块的函数耦合到led.c中。这样做除了隔离外部还可以提高程序的复用性。如果非要在.c文件中耦合全局变量或者其他模块的函数建议使用带参函数以及回调函数解决。这里有个问题,即便我外部不使用led_on()函数由于led.h中声明了它是一个全局函数,它始终对外开放,这在一定程度上是不符合封装思想,那么怎么办呢-结构体就可以实现这个功能。
(2)采用结构体做来封装数据与函数
在test.h声明如下结构
typedef struct
{
void (*fun1)();
void (*fun2)();
xxxx
int n.
}test_fun_t;
在test.c中定义并初始化结构体给应用者调用
test_fun_t test_init(void )
{
//创建一个fun_t型结构体
//确定fun1,fun2的指向哪个函数
}
在调用者文件app.c中
#include "test.h"
void app_test(void )
{
test_fun_t app_fun;
app_fun= test_init();
app_fun.n = 10;
app_fun.fun1();
app_fun.fun2();
}
由上可见结构体封住的好处
a)对于app.c来说,应用着是无需知道 app_fun.fun1(); app_fun.fun2();是如何实现的,他在test.c中实现。
b)app_fun.fun1,app_fun.fun2的重构不影响应用者
c) 在使用时创建,不使用时销毁,销毁后对应用者不开放test.c的任何函数,方便管理
d)可以使用test_fun_t 类型定义的变量做为函数参数传递给另外一个函数
e)在程序的阅读上能让人觉得他们是一组相关功能,提高可读性
下回在说说继承与多态
|