最近在用 C 做项目,之前用惯了 C++ ,转回头来用C 还真有点不适应。 C++ 语言中自带面向对象支持,如封装、继承、多态等面向对象的基本特征。 C 原本是面向过程的语言,自身没有内建这些特性,但我们还是可以利用 C 语言本身已有的特性来实现面向对象的一些基本特征。接下来我们就一一来细说封装、继承、多态、纯虚类等面向对象特性在 C 语言中如何实现,并且给出实例。
这篇文章中我们先说封装和继承。
先来看封装。
所谓封装,通俗地说,就是一个姑娘化了妆,只给你看她想让你看的那一面,至于里面是否刮了骨、垫了东西,不给你看。说到封装就得说隐藏,这是对兄弟概念;其实我理解隐藏是更深的封装,完全不给你看见,而封装可能是犹抱琵琶半遮面。封装在 C++ 语言中有 protected 、 private 关键字在语言层面上支持,而 C 语言中没有这些。 C 有结构体( struct ),其实可以实现封装和隐藏。
在 QT 中,为了更好的隐藏一个类的具体实现,一般是一个公开头文件、一个私有头文件,私有头文件中定义实现的内部细节,公开头文件中定义开放给客户程序员的接口和公共数据。看看 QObject (qobject.h ),对应有一个 QObjectPrivate (qobject_p.h ) ,其他的也类似。而代码框架如下:
这样做的好处是显而易见的,除了预定义好的接口,客户程序员完全不需要知道实现细节,即便实现经过重构完全重来,客户程序员也不需要关注,甚至相应的模块连重新编译都不要——因为 abc.h 自始至终都没变过。
上面代码有个问题,客户程序员如何得到 struct st_abc 的一个实例,他不知道 struct st_abc_private 如何实现的呀。 C 中没有构造函数,只好我们自己提供了:我们可以在 abc.h 中声明一个类似构造函数的函数来生成 struct st_abc 的实例,名字就叫作 new_abc() ,函数原型如下:
什么是继承?在面向对象层面上不讲了,只说语法层面。语法层面上讲,继承就是派生类拥有父类的数据、方法,又添了点自己的东西,所谓子承父业,发扬光大。在 C 语言中可以用结构体的包含来实现继承关系。代码框架如下:
继承在语法层面上看,有数据成员、函数,数据成员通过上面的方法自动就“继承”了,至于函数,在结构体表示为函数指针,其实也是一个数据成员,是个指针而已,也会自动“继承”。之所以还要在这里列出来说明,是因为 C++ 中有一个很重要的概念:重载。要在 C 中完整实现有点儿麻烦。
重载,我们常说的重载大概有三种含义:
我们平常在交流时通常不明确区分上面三种类型的重载,这里出于习惯,也不作区分。
好了,第一篇就到这里,有时间会往下续。
联系客服