这篇文章只适用于有 C 或 C++ 基础的人看,没有基础建议先去了解一下基础知识,我会结合之前我上课老师讲的内容,以及我自己的理解,有的放矢的讲,而且绝对不会掺杂很多废话,各位读者轻喷~
面向对象的由来以及发展我就不讲了,感兴趣的读者可以百度,嗯,百度。这里稍微说一下基本概念,对象(帮助理解现实世界,为计算机应用提供现实基础),类(描述一组相关对象),属性(对象的特证,也称为特性),函数(对象执行的活动),大概给个结构图,来展示他们之间的关系
图 2-1 类与简单对象关系图
我再举个例子来说明,狗是一个类,而狗中的吉娃娃,牧羊犬,小白狗...... 是狗这个类的具体个体(也就是我们所说的对象),每个对象都有他自己的属性和函数(行为),下面再给个图来说明
图 2-2 狗类和对象
思考:某公司的一名职员,我们怎么抽象出一个类和对象,先思考一下再看图
图 2-3 职员类
面向对象的思想(重点!重点!重点!)
首先考虑你要分析的问题里有哪些类和对象? 其次考虑这些类和对象应该具有哪些属性和方法? 最后考虑类和类、类和对象之间具备哪些关系?
说明部分:说明该类中的成员,包含数据成员的说明和成员函数的说明 实现部分:对成员函数的定义
2.2.2 类的一般定义格式
我用一张图来解释如何定义类
2.2.3 类定义的说明
访问权限修饰符:公有的 (public)、私有的 (private) 和保护的 (protected)
访问权限修饰符出现的先后次序无关,并且允许多次出现
缺省访问权限为私有的
公有部分:一些操作(即成员函数),是提供给用户的接口功能
私有部分:一些数据成员,通常用来描述该类中的对象的属性
2.2.4 示例
下面给出一个时间类,这个时间类中有三个成员函数,作用分别是:设置时间、判断是否为闰年、打印时间,同时还有三个私有成员变量,分别是 year、month、day
图 2-5 时间类代码
2.2.5 定义类时的注意事项
在类体中不允许对所定义的数据成员进行初始化
类中的数据成员的类型可以是任意的:
(1) 包含整型、浮点型、字符型、数组、指针和引用等
(2) 另一个类的对象,可以作该类的成员
(3) 自身类的对象不可以作该类的成员
(4) 自身类的指针或引用,可以作该类的成员
(5) 当另一个类的对象作为该类的成员时,如果另一个类的定义在后,需要提前说明
(6) 一般在类体内先说明用户感兴趣的公有成员,再说明私有成员
(7)习惯将类定义的说明部分或者整个定义部分 (包含实现部分) 放到一个头文件中
2.3.1 对象的一般定义格式
<类名>(空格)<对象名表>
2.3.2 示例
图 2-7 对象的定义格式
2.3.3 对象成员的表示方法
这里有必要声明一下,成员有两类,一是成员变量,二是成员函数
(1) 一般对象
成员变量:<对象名>.<变量名>
成员函数:<对象名>.<函数名>(<参数表>)
(2) 指针对象
成员变量:<对象名>-><变量名>
成员函数:<对象名>-><函数名>(<参数表>)
(3) 引用对象
与一般对象相同
2.4.1 构造函数与析构函数的功能
构造函数:在创建对象时,使用特定的值来将对象初始化
析构函数:用来释放对象,在对象删除前做一些清理工作
2.4.2 构造函数与析构函数示例
图2-8 构造函数和析构函数代码
2.4.3构造函数的特点
构造函数是成员函数,函数体可写在类体内,也可写在类体外
构造函数的名字与类名相同
构造函数不指定返回类型,它有隐含的返回值,该值由系统内部使用
构造函数可以有一个或多个参数
构造函数可以重载
程序中不能直接调用构造函数,在创建对象时系统自动调用构造函数 构造函数的执行顺序与定义的顺序有关,先定义的对象,先调用构造函数
2.4.4 析构函数的特点
析构函数是成员函数,函数体可写在类体内,也可写在类体外
析构函数的名字在类名前加~ 字符
析构函数不指定返回类型
析构函数没有参数
一个类中只能定义一个析构函数 析构函数在对象存在的函数体结束时或使用delete运算符释放new运算符创建的对象时被自动调用
析构函数的执行顺序与定义顺序相反,先定义的对象,后调用析构函数 2.4.5缺省构造函数(默认构造函数)
类定义中没有任何构造函数时,由编译器自动生成一个不带参数的缺省构造函数
缺省构造函数即参数表为空的构造函数
2.4.6 缺省析构函数
定义时机同缺省构造函数
2.4.7补充内容:重载
重载的必要条件:
1.函数名相同
2.函数的参数不同(1函数的参数个数不同,2函数的参数类型不同)
3.函数的返回值不同不是重载条件
4.构造函数可以重载
5.析构函数不能重载
6.一般成员函数可以重载
2.5.1 拷贝初始化构造函数的功能
用一个已知的对象来初始化一个被创建的同类对象
2.5.2 特点
函数名与类名相同,无返回类型
只有一个参数,是对某个对象的引用
<类名>::<类名>(const <类名> & <引用名>)
每个类都必须有一个拷贝初始化构造函数
2.5.3 缺省拷贝初始化构造函数
如果类中没有说明拷贝初始化构造函数,则编译系统自动生成一个具有上述形式的缺省拷贝初始化构造函数,作为该类的公有成员
2.5.4 示例
图2-9 拷贝初始化构造函数
图2-10 程序运行结果
2.5.5 使用拷贝初始化构造函数的三种情况
明确表示由一个对象初始化另一个对象时 例如:TPoint N(M)
当对象作为函数实参传递给函数形参时(传值调用) 例如:P=f(N)
当对象作为函数返回值时(数据值) 例如:return R
2.6 内联函数和外联函数
2.6.1 内联函数
内联函数是指那些定义在类体内的成员函数,即该函数的函数体放在类体内
2.6.2 外联函数
声明在类体内,定义在类体外的成员函数,外联函数的函数体在类的实现部分
外联函数变成内联函数的方法很简单,只要在函数头前面加上关键字inline就可以了
2.6.3 示例
图2-11 内联函数与外联函数
2.7 设置参数的缺省值
一般成员函数和构造函数都可以被设置缺省参数值
示例:
图2-12 函数设置缺省参数值
2.8 静态成员
解决数据共享问题,即不通过全局对象,而实现多个对象之间的数据共享
2.8.1 静态数据成员
是类的所有对象共享的成员,而不是某个对象的成员
对多个对象来说,静态数据成员只存储在一个地方,供所有对象使用
静态数据成员的值对每个对象都是一样的,但其值可以被任何一个对象更新
2.8.2 使用方法与注意事项:
静态数据成员在定义或说明时前面加上关键字static
静态数据成员是静态存储的,它是静态生存期,必须对它进行初始化
初始化格式:<数据类型> <类名>::<静态数据成员名>=<值>
初始化在类体外进行,前面不加static,以免与一般静态变量或对象混淆
初始化时不加该成员的访问权限控制符(静态数据成员初始化位置与访问权限无关)
初始化时使用作用域运算符表明它所属的类
引用格式:<类名>::<静态成员名>
2.8.3 示例:
图2-13 静态数据成员
图2-14 静态变量Sum
2.8.4 静态成员函数
作用:操作静态数据成员
使用格式:<类名>::<静态成员函数名>(<参数表>)
注意事项:静态成员函数的实现中不能直接引用类中说明的非静态成员,可以引用类中说明的静态成员
静态成员函数中要引用非静态成员时,可以通过对象来引用
2.8.5 示例:
图2-14 静态成员函数
2.9 友元
2.9.1 为什么引入友元?
在对某些成员函数多次调用时,由于参数传递、类型检查和安全性检查等都需要时间开销,从而影响了程序的运行效率,引入友元后可以提高程序的运行效率,友元分友元函数和友元类
2.9.2 使用格式
定义在类外部的类或普通函数,但需要在类体内进行说明(前面加friend关键字)
不是成员函数,但可以访问类中的私有成员
2.9.3 示例
图2-15 友元函数
图2-16友元类
2.10 对象的生存期
指对象从被创建开始到被释放为止的时间
2.10.1按生存期对对象的分类
局部对象:被定义在一个函数体或程序块内,作用域小,生存期短
静态对象:被定义在一个文件中,它的作用域从定义时起到文件结束时止;它的作用域较大,生存期也较长
全局对象:被定义在某个文件中,它的作用域在包含该文件的整个程序中;它的作用域最大,生存期最长
2.10.2 示例
图2-17 对象的生存周期
传送门:1小时掌握c++面向对象编程