#287. 第三节 面向对象
第三节 面向对象
编程语言分类
编程语言分为两类:面向对象与面向过程。常见的面向对象语言有C++、Java、Python等,常见的面向过程语言有C、Fortran等。
一、类
1. 类的概念
类是对数据的一种抽象,是用户自定义的数据类型,并且类中还拥有方法,即成员函数。在类中的内容可以分为三类:
- public:表示公有,类的数据成员和函数可以被该类和派生类(知识点四)访问。
- private:表示私有,自己的类可以访问,但派生类不可访问。
- protected:表示保护,自己的类和派生类可以访问。
2. 类的声明方法

3. People类
3.1 代码

3.2 构造函数和析构函数
由于对象一定会在内存中占有一段空间,所以一定会有其生命周期,即有申请内存空间和释放内存空间的步骤。
- 构造函数:是指当对象申请内存空间之后自动调用的函数。在产生实例时自动运行的函数。构造函数只能在类中声明,且没有返回值。构造函数的函数名必须与类名一致。
- 析构函数:是指当对象的空间即将被销毁前自动调用的函数。析构函数的声明需要在类中声明,且没有返回值与参数列表。析构函数的函数名必须为
~+类名。
3.3 类的定义
类的定义主要是对类中的成员函数进行定义。当成员函数在类外进行定义时,要在函数名前加上类名::以表示是成员函数,对于不同的类,可以有同名的成员函数。
3.3.1 this指针
在类成员函数中可以自由访问该类的其他成员和成员函数,可以通过this指针来访问自己的地址,得到所需要的数据。
- 使用格式:

3.3.2 定义类成员函数的语法

3.3.3 People类成员函数定义实例

二、对象和对象的使用
1. 对象的概念
在C++中,对象一般指类在内存中装载的实例,有相关的成员变量和成员函数。类是抽象的概念,而对象是通过类实现的具体实例。
2. 创建与使用对象
在构建好类后,即可创建对象。即声明类变量。
2.1 创建对象格式
创建对象时需参考构造函数的格式。


这样便定义了一个20岁男性名字为Tom的People类变量p。
2.2 对象的使用
在创建好对象后,我们还可以使用对象的成员函数,使用方法如下:

这个语句调用了p对象的show成员,最后会自动调用析构函数销毁对象。
所创建的每个新对象都有自己的存储空间,用于存储其内部变量和类成员;但同一个类的所有对象共享同一组类方法,即每个对象只有一个副本。
三、友元
C++控制对类对象私有(private)部分的访问,一般情况下,通过公有(public)类方法提供唯一的访问途径,但有时候这种限制过于严格,以致于不适合特定的编程问题。在这种情况下,C++提供了另外一种形式的访问权限:友元。友元有三种:
- 友元函数
- 友元类
- 友元成员函数
3.1 友元函数
友元函数可以直接访问类的私有成员。它定义在类外,不属于任何类,但在使用时,需要在类的定义中加以声明。声明时只需在前额外加上关键字friend。
3.1.1 不加friend关键字代码示例

可以看到,程序会发生报错,因为无法访问People类中的私有成员age。
3.1.2 加上friend关键字代码示例

可以看到,在类中声明了友元函数后,函数即可访问对象的私有成员。
3.2 友元类
当友元函数非常多时,使用起来可能就比较麻烦,于是,友元类出现了。友元类即其中所有成员函数都是另一个类的友元函数。定义友元类的语句格式如下:


3.3 友元成员函数
友元类相对来讲的权限有些过大,所以比较中和的友元成员函数出现了,即让一个类中的某个或某些成员函数成为另一个类的友元函数。

四、类继承
面向对象编程的主要目的之一就是提供可重用的代码。C++提供了比修改代码更好的方法来扩展和修改类,这种方法叫类继承,类继承能从已有的类派生出新的类,而派生类继承了原有类(称为基类)的特征,包括方法。通过继承可以实现:
- 可以在已有类的基础上添加功能。
- 可以给类添加数据。
- 可以修改类方法的行为。
派生类需要自己的构造函数,可以根据需要添加额外的数据成员和成员函数。
4.1 继承自People类的Student类

对于性别、年龄、名字,在People类中已存在,所以在继承后,People类的代码中无需再出现此部分,同时,Student类可定义属于自己的构造函数:
...
4.2 Student类对象的使用

可以看到直接调用了People类的析构函数,所以,使用继承可以使我们的对象功能变得更为强大多元化。
五、运算符重载
C++中的运算符正常情况下只能使用于基本数据类型,不能使用于我们自定义的对象。运算符重载则是可以为运算符赋予新的功能,使之可以应用于对象的运算。
运算符重载的实质是编写以运算符作为名称的函数。不妨把这样的函数称为运算符函数。运算符函数的格式如下:

包含被重载的运算符的表达式会被编译成对运算符函数的调用,运算符的操作数成为函数调用时的实参,运算的结果就是函数的返回值。运算符可以被多次重载。
代码示例

六、习题
- CSP-J2022第一轮 以下哪种功能没有涉及C++语言的面向对象特性支持:
{{ select(1) }}
- C++中调用printf函数
- C++中调用用户定义的类成员函数
- C++中构造一个class或struct
- C++中构造来源于同一个基类的多个派生类
- CSP-J2021第一轮 以下不属于面向对象程序设计语言的是:
{{ select(2) }}
- C++
- Python
- Java
- C
- 模拟题 下列关于类和对象说法错误的是:
{{ select(3) }}
- 一个类只能有一个对象
- 对象是类的具体实例
- 类是对某一类对象的抽象
- 类和对象的关系是一种数据类型和变量的关系
- 模拟题 面向对象程序设计思想的主要特征不包括:
{{ select(4) }}
- 封装性
- 多态性
- 继承性
- 功能分解,逐步求精
- 模拟题 下列有关C++类的说法中,不正确的是:
{{ select(5) }}
- 类是一种用户自定义的数据类型
- 只有类中的成员函数或类的友元函数才能存取类中的私有成员
- 在类中,如果不做特别说明,所有成员的访问权限均为私有的
- 在类中,如果不做特别说明,所有成员的访问权限均为公用的
- 模拟题 下面说法中,正确的是:
{{ select(6) }}
- 一个类只能定义一个构造函数,但可以定义多个析构函数
- 一个类只能定义一个析构函数,但可以定义多个构造函数
- 构造函数与析构函数同名,只要名字前加了一个求反符号(~)
- 构造函数可以指定返回类型,而析构函数不能指定任何返回类型,即使是void类型也不可以