文章目录
- 📚面向对象程序设计的基本特点
- 🐇抽象——概括问题,抽出公共性质并加以描述。
- 🐇封装——将抽象所得数据和行为相结合,形成一个有机的整体,形成“类”。
- 🐇继承——在原有类特性的基础上,进行更具体、更详细的说明。
- 🐇多态——处理多种类型对象的能力。
- 📚类与对象
- 🐇类的定义
- 🐇类成员的访问控制
- 🐇类的对象:一个特定实体
- 🐇类的成员函数
- 📚构造函数和析构函数
- 🐇构造函数——用于对象的初始化
- 🐇析构函数——用于对象的清理
- 📚类的组合
- 📚结构体与联合体
- 🐇结构体
- 🐇联合体
📚面向对象程序设计的基本特点
🐇抽象——概括问题,抽出公共性质并加以描述。
数据抽象
:描述某类对象的属性或者状态,也就是此类对象区别于彼类对象的特征。类似于时钟的时、分、秒。行为抽象
:某种对象的共同行为或功能特征。类似于时钟显示时间设置时间等的简单功能。
🐇封装——将抽象所得数据和行为相结合,形成一个有机的整体,形成“类”。
🐇继承——在原有类特性的基础上,进行更具体、更详细的说明。
🐇多态——处理多种类型对象的能力。
- “打”可以“打篮球”“打排球”“打羽毛球”
- 表面的多态性
- 强制多态——将一种类型的数据转换成另一种类型的数据。
- 重载多态——给同一个名字赋予不同的含义。
- 真正的多态性
- 包含多态——虚函数实现。
- 类形参化多态——模块实现。
📚类与对象
🐇类的定义
- 格式
class 类名称 { public: //外部接口 protected: //保护性成员 private: //私有成员 };
- 数据成员:数据(时钟的时分秒)
- 函数成员:行为(时钟显示时间)
- 注意,在类中可以只声明函数的原型,函数的实现(即函数体)可以在类外定义。
🐇类成员的访问控制
公有类型
(public):公有类型成员定义了类的外部接口。在类外只能访问类的公有成员。私有类型
(private):私有成员只能被本类的成员函数访问,来自类外部的任何访问都是非法的。- 一般情况下,一个类的数据成员都应该声明为私有成员,这样,内部数据结构就不会对类以外的其余部分造成影响,程序模块之间的相互作用就会被降低到最小。
- 如果私有成员紧接着类名称,则关键字private可以省略。
保护类型
(protected):和私有成员的性质相似,其差别在于继承过程中对产生的新类的影响不同(后续补充- 规则
- 在类的定义中,具有不同访问属性的成员,可以任意顺序出现。
- 修饰访问属性的关键字也可以多次出现。
- 但是一个成员只能具有一种访问属性。
- 习惯:在书写时通常习惯将公有类型放在最前面,这样便于阅读。
🐇类的对象:一个特定实体
- 整个公司的雇员看做一个类,那么每一个雇员就是该类的一个特定实体,也就是一个对象。
- 对象的声明:
类名 对象名
Clock myClock
- 对象所占据的内存空间只是用于存放数据成员,函数成员不在每一个对象中存储副本,每个函数的代码在内存中只占据一部分空间。
- 访问对象的成员:
对象名.数据成员名
- 调用函数成员:
对象名.函数成员名(参数表)
,myClock.showTime()
。 - 类和对象的关系就相当于基本数据类型与它的变量的关系,也就是一般与特殊的关系。
🐇类的成员函数
- 在类的外部只能访问到类的公有成员;在类的成员函数中可以访问到类的全部成员。
- 成员函数的实现:与普通函数不同的是,实现成员函数时要指明类的名称。
- 成员函数调用中的目的对象:使用
myClock.showTime()
调用showTime函数时,myClock就是这一调用过程的目的对象。
- 带默认形参值的成员函数
- 类成员函数的默认值,一定要写在类定义中,而不能写在类定义之外的函数实现中。
- 默认参数设置就是当这个函数没有给出实参,就会按照默认形参值调用。
- 若给某一参数设置了默认值,那么在参数表中其后所有的参数都必须设置成默认值。
- 内联成员函数
- 简单讲就是写在类定义里的函数。
- 在编译时被插入到每一个调用它的地方,可以减少调用的开销,提高执行效率。但是却增加了编译后代码的长度,所以只有相对简单的成员函数才可以声明为内联函数。
- 隐式声明
- 显示声明:类定义中不加入函数体,但在返回类型前加上
inline
,效果和隐式表达式完全相同的。
📚构造函数和析构函数
🐇构造函数——用于对象的初始化
- 构造函数的特点
- 构造函数的作用就是在对象被创建时利用特定的值构造对象,将对象初始化于一个特定的状态。
- 构造函数也是类的一个成员函数,除了具有一般成员函数的特征之外,构造函数:
- 构造函数的函数名与类名相同。
- 没有返回值。
- 通常被声明为公有函数。
- 构造函数在对象被创建时被自动调用。
- 调用时无须提供参数的构造函数称为默认构造函数。如果类中没有写构造函数,那么编译器会自动生成一个隐含的默认构造函数。
- 复制构造函数
-
它是一个特殊的构造函数,具有一般构造函数的所有特性。其形参是本类的对象的引用。
-
其作用是使用一个已经存在的对象(由复制构造函数的参数指定),去初始化同类的一个新对象。
-
如果程序员没有写,那么系统就会在必要时自动生成一个隐含的复制构造函数。将初始值对象的每个数据成员的值都复制到新建立的对象中。
-
⭐️普通构造函数在对象创建时被调用,而复制构造函数在以下三种情况下被调用:
- 用类的一个对象去初始化该类的另一个对象。
- 如果函数的形参是类的对象,调用函数时,进行形参和实参结合。
- 函数的返回值是类的对象,函数执行完成返回调用时。如下:表面上函数g将a返回给了主函数,但是a是
g()
的局部对象,离开建立它的函数g以后就消亡了,所以需要复制构造函数。
- 用类的一个对象去初始化该类的另一个对象。
-
🐇析构函数——用于对象的清理
- 析构函数是在对象的生存期快结束时被自动调用的。
- 与构造函数一样,析构函数通常也是类的一个公有函数成员,它的名称是由类名前面加
~
构成的,没有返回值,不接收任何参数,但可以是虚函数。(虚函数后面补充)。 - 不进行显式说明,系统也会生成一个函数体为空的隐含析构函数,而且它未必不做任何事(后续介绍)。
- 一般来讲,如果希望程序在对象被删除之前的时刻自动完成某些事情,就可以把它们写到析构函数中。
📚类的组合
- 类的组合就是一个类内嵌其他类的对象作为成员,它们之间的关系是一种包含与被包含的关系。
- 当创建类的对象时,如果这个类具有内嵌对象成员,那么各个内嵌对象首先将被自动创建。
- 在创建对象时既要对本类的基本类型数据成员进行初始化,又要对内嵌对象成员进行初始化。
- 一般形式为:
- ⭐️组合类对象的构造函数的调用顺序
- (1)调用内嵌对象的构造函数,调用顺序按照内嵌对象在组合类的定义中出现的次序。注意,内嵌对象在构造函数的初始化列表中出现的顺序与内嵌对象构造函数的调用顺序无关。
- (2)执行本类构造函数的函数体。
- ⭐️析构函数则正好相反
- 如果要为组合类编写复制构造函数,则需要为内嵌成员对象的复制构造函数传递参数。
📚结构体与联合体
🐇结构体
- 它和类的功能完全相同,但引入结构体可保持和C程序的兼容性。
struct 结构体名称 { //公有成员 protected: //保护性成员 private: //私有成员 };
- 结构体是一种特殊形态的类,可以:
- 有自己的数据成员和函数成员。
- 有自己的构造函数和析构函数。
- 控制访问权限。
- 支持包含多态等。
- 区别在于结构体和类有不同的默认访问控制属性。
- 在类中,对于未指定访问控制属性的成员,其访问控制属性为私有类型;
- 在结构体中,没指定的为公有类型。
🐇联合体
- 基本结构
union 联合体名称 { //公有成员 protected: //保护性成员 private: //私有成员 };
- 联合体也是一种特殊形态的类,可以:
- 有自己的数据成员和函数成员。
- 有自己的构造函数和析构函数。
- 控制访问权限。
- 由C语言继承而来。
- 默认访问控制属性也是公用的。
- 但其全部数据成员共享一组内存单元,因此一组数据中,任何两个数据不会同时有效。
- 限制:
- 联合体的各个对象成员(及其对象成员的对象成员以此类推),不能有自定义的构造函数,自定义的析构函数和重载的复制赋值运算符。
- 联合体不能继承。
- 不支持包含多态
- 一般联合体用来存储一些公有的数据,而不为它定义函数成员;联合体也可以不声明名称,称为无名联合体,通常作为内嵌成员。