封装
所谓的封装,其实就是将多个关联数据打包到一起,作为一个整体来看,也就是所谓的对象
对象是什么?对象是某个具体类型的一个实例化
那在C语言里面,我们有没有什么对关键数据打包的技术么?答案肯定是有
数据打包利器: struct , union
既然结构体或者共用体实例化就是对象,那如何面向这个对象编程呢?
不如我们遵从一个约定:针对某个对象的的操作函数,我们始终把这个对象放在参数的第一个位置
为什么呢?
这么说吧,如果针对某个对象的操作,不需要任何额外参数,那我们的第一个参数必定就是我们的对象参数,因为参数就它一个
那如果还有额外参数呢?那我们保持良好的习惯,始终在对象参数的后面增加其他参数,这样就能保持第一个参数始终都是我们的对象参数了
而这些函数所做任何操作,结果都会体现在两处:
慢慢的我们会形成一种思想,我们的接口函数,都是针对某个对象的,而这个对象,就是第一个参数
实际上,C++就是这么干的,只不过C++替我们做了第一个参数的自动传递,这个参数名字叫:this
继承
C里面没有继承 但我们可以换一种思路:继承的是什么?
首先,继承的肯定有基类的数据成员,然后是基类的操作接口
不如我们这样做:
在定义一个新结构体来扩展某个现有结构体的功能时,将已有结构体作为新结构体的第一个成员,并命名为parent或者base或者super等表示基类字段
然后我们的其他新增的字段都往下定义
为什么这样做呢?
因为这样可以保证这个结构的实例化对象的地址,既可以当做新结构体来用,也可以当成基类的结构体来用,因为他们的地址是一样的🤪
这样是不是就可以用“继承”后的新结构体的对象作为参数调用基类的接口了😎
是不是很牛逼
多态
多态,实际上就是函数名一样,基类和子类却干着不同的勾当🧐,没错吧
C里面可以用啥来这么干呢?
嘿嘿,函数指针也可以
我们可以定义一个结构体,成员里面放上一个函数指针(这个函数指针所对应的函数也要保持第一个参数是当前结构体对象的指针)
在基类的初始化过程中,我们把基类操作的具体函数赋值给这个函数指针,在子类结构体的初始化里面,我们偷偷把这个函数指针指向子类的新函数
然后这个结构体在使用的时候,我们随便调用这个函数指针,实际上基类和子类调用的具体函数实现也不是同一个,相当于用另类方式实现了多态
泛型
泛型,在C++里面也称为模板
在C里面能用吗?
直接用当然没办法,但我们也可以换一种思路呀
模板类型包括哪三个要素?
或者换个说法:一个具体的对象包括哪三要素?
地址,大小,与类型
在C++里面体现为: 地址,大小,构造函数
那么我们可以使用一个通用的字段表示地址,然后一个字段表示大小,至于构造函数,我们在写具体的对象初始化的时候基本上都会写
地址我们用void * 大小我们用sizeof的返回类型size_t
所以这里我们用地址加大小,就可以表示一个模板参数了,只不过我们用的时候必须要自己有所意识:当前用的这个对象是哪个类型?
当我们写出了一些包含了地址和大小的接口函数时,我们其实提供的是一个相当于模板类型的接口,比如标准库的write接口,我们可以传各种结构体的地址,然后传递sizeof的结果作为大小,这样我们几乎可以对任何类型做相同的操作
常见的有结构体字节信息,管理结构体的内存分配,释放与拷贝等等
|