谈谈C语言的面向对象
一.个人的一些理解
我们知道C++其实是从C语言发展而来的。C语言的绝大部分语法在C++同样适用,C++扩展了C语言。最明显的区别是C++有了类的语法,从而延伸出了对象的概念,拥有继承和多态性等等。其实在C语言里面结构体和C++的类是非常相似的,我们可以使用结构体实现类的绝大部分功能。因此,C主要是通过结构体去实现我们所说的面向对象的思想。如果了解过linux内核的源码(linux内核是由C语言实现的),我们会发现里面用到了大量的结构体,到处都弥漫着面向对象的气息。
结合上诉的描述,实操几个实例,初步了解下C语言是如何实现面向对象的。首先声明下,本篇文章只不过是作者自己的一个感悟,很有可能存在偏颇,不正确的地方,不必过于严肃对待,能够体会就体会,觉得误人子弟,请一笑而过。
对于面向对象里面比较重要的概念,继承和多态,C语言是如何实现呢?
继承的话,可以有一个父类的结构体,然后在子类结构体里面添加父类结构体作为成员变量即可。
多态的实现,可以通过同一个函数指针,对于同一个子类的不同实例化对象,指向不同的实现函数,即不同的方法,实现多态功能。
二.实例介绍
在实例中我会使用两个嵌入式常用到的例子,指示灯和延时。那么指示灯和延时怎么就和面向对象关联上了呢?使用指示灯的时候我们经常会用该各种不同的频率,1Hz,10Hz,等等,使用延时的时候,延时时间更是不确定。下面分开来讲。
例子还是比较肤浅,没有讲到继承和多态,主要是先引出以及理解这么一个概念,后续再更新迭代。
2.1指示灯类
我在这里把指示灯当作一类,即不管是红灯也好,绿灯也好,闪烁周期是1s或者0.5s等等。把它做成一类,然后在里面提供方法接口,根据传入的参数,由方法自己决定闪烁周期等等。
2.2延时类
延时有什么好归类的呢?不就delay_ms(),delay_us()等等。这些延时都是死等,在延时的过程中没法处理其他事情(除了中断产生及其里面的处理)。那如何实现延时的效果,同时又能处理其他事情呢?或许你会想到在定时器里面设标志位,到时间就清除标志位,等操作,但这种延时多了并不好维护,也不容易阅读。又或者用操作系统,有时候我们并不想什么都上操作系统。那好,延时类会给你答案,可以创建一个延时类,使用接口方法实现不同时长的延时,并且也不会阻塞等待。
三.例程源码
直接看源码体会吧,talk is cheap,show me the code. 你知道啥意思吗?是谁说的?
在windows平台下编译测试的,源码只是简单的实现框架和基础的功能,有兴趣的网友可以在此基础上“魔改”。
#include<stdio.h>
#include<time.h>
#include<windows.h>
/*************指示灯类的闪烁******************/
typedef struct _signal_lamp
{
char start_flag;
unsigned int count;
unsigned int middle;
unsigned int bottom;
void (* signal_on)(void);
void (* signal_off)(void);
void (* signal_updata)(struct _signal_lamp *signal);
void (* disable_signal)(struct _signal_lamp *signal);
void (* enable_signal)(struct _signal_lamp *signal,unsigned int middle,unsigned int bottom);
}SIGNAL_LAMP;
void singal_on(void)
{
printf("on\n");
}
void singal_off(void)
{
printf("off\n");
}
void disable_signal(struct _signal_lamp *signal)
{
signal->start_flag = 0;
signal->count =0;
}
void enable_signal(struct _signal_lamp *signal,unsigned int middle,unsigned int bottom)
{
signal->start_flag = 1;
signal->middle = middle;
signal->bottom = bottom;
}
//放到轮询中去
void signal_updata(SIGNAL_LAMP *signal)
{
if(signal->start_flag == 1){
signal->count++;
if( signal->count <= signal->middle){
signal->signal_on();
}else if(signal->count < signal->bottom){
signal->signal_off();
}else{
signal->count = 0;
}
}else{
signal->count = 0;
}
}
void signal_init(
SIGNAL_LAMP *signal,
void (* signal_on)(void),
void (* signal_off)(void)
)
{
signal->start_flag = 0;
signal->count = 0;
signal->middle = 0;
signal->bottom = 0;
signal->signal_on = signal_on;
signal->signal_off = signal_off;
signal->signal_updata = signal_updata;
signal->disable_signal = disable_signal;
signal->enable_signal = enable_signal;
}
SIGNAL_LAMP my_signal;
/***************延时处理模块*****************/
typedef struct _delay_module
{
char delay_enable;
unsigned int delay_count;
void (* updata_delay_time)(struct _delay_module *delay_time);
char (* is_delay_over)(struct _delay_module *delay_time);
void (* start_delay)(struct _delay_module *delay_time,unsigned int delay_count);
void (* disable_delay)(struct _delay_module *delay_time);
}DELAY_MODULE;
void updata_delay_time(DELAY_MODULE *delay_time)
{
if(delay_time->delay_enable == 1){
if(delay_time->delay_count > 0){
delay_time->delay_count --;
}
}
}
char is_delay_over(DELAY_MODULE *delay_time)
{
if(delay_time->delay_count == 0){
delay_time->disable_delay(delay_time);
return 1;
}else{
return 0;
}
}
void start_delay(DELAY_MODULE *delay_time,unsigned int delay_count)
{
if(delay_time->delay_enable == 0){
delay_time->delay_count = delay_count;
delay_time->delay_enable = 1;
}
}
void disable_delay(DELAY_MODULE *delay_time)
{
delay_time->delay_enable = 0;
delay_time->delay_count = 0;
}
void init_delay(DELAY_MODULE *delay_time)
{
delay_time->delay_enable = 0;
delay_time->delay_count = 0;
delay_time->start_delay = start_delay;
delay_time->updata_delay_time = updata_delay_time;
delay_time->is_delay_over = is_delay_over;
delay_time->disable_delay = disable_delay;
}
DELAY_MODULE my_delay;
/*******************************************/
DWORD WINAPI ThreadFun(LPVOID pM)
{
while(1)
{
my_signal.signal_updata(&my_signal);
my_delay.updata_delay_time(&my_delay);
Sleep(200);
}
}
DWORD WINAPI ThreadFun2(LPVOID pM)
{
while(1)
{
Sleep(5000);
my_signal.disable_signal(&my_signal);
printf("disable\n");
}
}
DWORD WINAPI ThreadFun3(LPVOID pM)
{
while(1)
{
my_delay.start_delay(&my_delay,20);
if(my_delay.is_delay_over(&my_delay) == 1){
printf("delay is over\n");
}
Sleep(5);
}
}
void create_thread(void)
{
HANDLE handle = CreateThread(NULL,0,ThreadFun,NULL,0,NULL);
HANDLE handle2 = CreateThread(NULL,0,ThreadFun2,NULL,0,NULL);
HANDLE handle3 = CreateThread(NULL,0,ThreadFun3,NULL,0,NULL);
WaitForSingleObject(handle, INFINITE);
WaitForSingleObject(handle2, INFINITE);
WaitForSingleObject(handle3, INFINITE);
}
void main(void)
{
signal_init(&my_signal,singal_on,singal_off);
my_signal.enable_signal(&my_signal,10,21);
init_delay(&my_delay);
printf("thread examples\n");
create_thread();
while(1){
}
}