通过点灯学习C的面向对象编程思想
面向对象思想是什么?
有的人说C语言是一门面向过程的编程语言,但是面向过程只是一种设计思想,而不是某种语言的私有财产。那什么是面向过程思想,什么是面向对象思想?
面向过程专注于“先A,再B,然后C”的流程,适合解决线性的任务。
面向对象专注于“谁?什么状态?能干什么?”,适合复杂系统,例如linux内核。
为什么我们要学习面向对象思想?
你有没有过这种体验?读别人写的C语言项目,跟着一个函数跳来跳去,数据传来传去,改一个结构要动十个文件… 感觉自己不是在读代码,而是在走迷宫;或者当你自己写一个稍大的程序时,变量越加越多,函数越改越乱,到最后连自己都理不清。这通常不是C语言的错,而是我们被“一步一步来”的面向过程思维框住了。
面向对象思想可以帮助我们把复杂系统拆分成职责清晰的模块,减少函数跳转和全局状态的传播,使代码更易读、可维护并且便于扩展。
下面本文将从介绍C语言如何运用结构体、函数指针实现面向对象编程的核心理念——抽象、封装、继承与多态。
面向对象的四大基本特性
抽象
我们可以对现实存在的各种事物进行抽象,把它封装成一种数据类型——类。
无论壁灯、吊灯、吸顶灯,他们都是灯,拥有各自的特点,我们可以将这些共同的东西进行抽象,封装成Lamp这个类。
封装
封装则是将灯的属性和方法都封装到一个结构体里。封装后的结构体就相当于一个类。
typedef struct Lamp { |
这样我们就得到了我们的Lamp类啦,但是子类想要使用该类的属性和方法该如何继承呢?
继承
我们封装一个类的目的就是为了继承,从而实现代码的复用。
继承的实现:将基类放在结构体开头来模拟继承。
/* "子类":FlashingLamp */ |
如代码所示,我们在结构体类型FlashingLamp里面内嵌了结构体类型Lamp,此时FlashingLamp就相当于模拟了一个子类,而Lamp相当于父类。通过这种内嵌就实现了子类继承了父类的属性和方法。
子类不仅可以直接复用父类中定义的属性和方法,还可以在父类的基础上拓展自己的属性和方法。
对于不同的灯我们打开的方式也不一样,所以我们可以在继承的过程中重新定义父类。
多态
void flashing_turn_on(Lamp *self) { |
如上所示,我们通过基类指针去调用子类中的不同实现,就叫作多态。
