在面向对象的语言里面,出现了类的概念。类是对特定数据的特定操作的集合体。类包含了两个范畴:数据和操作。而C语言中的struct仅仅是数据的集合,我们可以利用函数指针将struct模拟为一个包含数据和操作的“类”。
用c程序模拟一个最简单的“类”:
#define C_Class struct
C_Class A
{
C_Class A *A_this; //this指针
void (*foo)(C_Class A *A_this); //行为:函数指针
int (*parea)(int length,int width);
int a; //数据
int b;
}
例:菜单操作
要求以键盘上"<—— ——>"键切换菜单焦点,当用户在焦点处于某菜单时,若敲击键盘上的OK、CANCEL键则调用该焦点菜单对应的处理函数。当前有四个菜单选项。
实现方法1:
用C语言面向过程的知识来完成任务。
//按下ok键
void onOKKey()
{
//判断在什么焦点菜单上按下ok键,调用相应处理函数
switch(currentFocus)
{
case MENU1: menu1OnOk();break;
case MENU2: menu2OnOk();break;
......
}
}
//按下cancel键
void onCancelKey()
{
//判断在什么焦点菜单上按下ok键,调用相应处理函数
switch(currentFocus)
{
case MENU1: menu1OnCancel();break;
case MENU2: menu2OnCancel();break;
......
}
}
因为用到ok和cancel这两个键,所以设立onokkey和oncancelkey两个函数。在函数体内使用switch判断在哪个菜单选项焦点按下ok键或者cancel键。
如果后续增减菜单选项怎么办?
则需在两个函数体的switch增加case。
实现方法2:
用C语言面向对象化的方法。
//将菜单的属性和操作“封装”在一起,声明菜单项的“类”
typedef struct tagSysMenu
{
char *text; //菜单的文本
BYTE xPos; //菜单在LCD上的x坐标
BYTE yPos; //菜单在LCD上的y坐标
void (*onOKFun)(); //在该菜单上按下ok键的处理函数指针,用来模拟类当中的成员函数
void (*onCancelFun); //在该菜单上按下cancel键的处理函数指针
}SysMenu,*LPSysMenu;
//用结构体数组来实现每一个菜单项
static SysMenu menu[MENU_NUM]=
{
//声明数组的同时对数组的成员做初始化
{ "menu1",0,48,menu1OnOk,menu1OnCancel},
{ "menu2",7,48,menu2OnOk,menu2OnCancel},
{ "menu3",14,48,menu3OnOk,menu3OnCancel},
......
};
//按下ok键
void onOkKey()
{
menu[currentFocusMenu].onOkFun();
}
//按下cancel键
void onCancelKey()
{
menu[currentFocusMenu].onCancelFun();
}
如果后续增减菜单选项怎么办?
则需在结构体数组menu中增加数据,并更改MENU_NUM。
结论:
1.程序被大大简化了,也开始具有很好的可扩展性。
2.利用了面对对象中的封装思想,使程序结构清晰,其结果是几乎可以在无需修改程序的情况下在系统中添加更多的菜单,而系统的按键处理函数保持不变。
*笔记内容来源于mooc-嵌入式软件设计-赖晓晨老师。