#287. 第三节 面向对象

第三节 面向对象

编程语言分类

编程语言分为两类:面向对象与面向过程。常见的面向对象语言有C++、Java、Python等,常见的面向过程语言有C、Fortran等。


一、类

1. 类的概念

类是对数据的一种抽象,是用户自定义的数据类型,并且类中还拥有方法,即成员函数。在类中的内容可以分为三类:

  1. public:表示公有,类的数据成员和函数可以被该类和派生类(知识点四)访问。
  2. private:表示私有,自己的类可以访问,但派生类不可访问。
  3. protected:表示保护,自己的类和派生类可以访问。

2. 类的声明方法

![](file://_9KucM_RG_dWFqBuoNeF9.png)

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++提供了另外一种形式的访问权限:友元。友元有三种:

  1. 友元函数
  2. 友元类
  3. 友元成员函数

3.1 友元函数

友元函数可以直接访问类的私有成员。它定义在类外,不属于任何类,但在使用时,需要在类的定义中加以声明。声明时只需在前额外加上关键字friend

3.1.1 不加friend关键字代码示例

可以看到,程序会发生报错,因为无法访问People类中的私有成员age

3.1.2 加上friend关键字代码示例

可以看到,在类中声明了友元函数后,函数即可访问对象的私有成员。

3.2 友元类

当友元函数非常多时,使用起来可能就比较麻烦,于是,友元类出现了。友元类即其中所有成员函数都是另一个类的友元函数。定义友元类的语句格式如下:

3.3 友元成员函数

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

四、类继承

面向对象编程的主要目的之一就是提供可重用的代码。C++提供了比修改代码更好的方法来扩展和修改类,这种方法叫类继承,类继承能从已有的类派生出新的类,而派生类继承了原有类(称为基类)的特征,包括方法。通过继承可以实现:

  1. 可以在已有类的基础上添加功能。
  2. 可以给类添加数据。
  3. 可以修改类方法的行为。

派生类需要自己的构造函数,可以根据需要添加额外的数据成员和成员函数。

4.1 继承自People类的Student

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

4.2 Student类对象的使用

可以看到直接调用了People类的析构函数,所以,使用继承可以使我们的对象功能变得更为强大多元化。

五、运算符重载

C++中的运算符正常情况下只能使用于基本数据类型,不能使用于我们自定义的对象。运算符重载则是可以为运算符赋予新的功能,使之可以应用于对象的运算。

运算符重载的实质是编写以运算符作为名称的函数。不妨把这样的函数称为运算符函数。运算符函数的格式如下:

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

代码示例

六、习题

  1. CSP-J2022第一轮 以下哪种功能没有涉及C++语言的面向对象特性支持:

{{ select(1) }}

  • C++中调用printf函数
  • C++中调用用户定义的类成员函数
  • C++中构造一个class或struct
  • C++中构造来源于同一个基类的多个派生类
  1. CSP-J2021第一轮 以下不属于面向对象程序设计语言的是:

{{ select(2) }}

  • C++
  • Python
  • Java
  • C
  1. 模拟题 下列关于类和对象说法错误的是:

{{ select(3) }}

  • 一个类只能有一个对象
  • 对象是类的具体实例
  • 类是对某一类对象的抽象
  • 类和对象的关系是一种数据类型和变量的关系
  1. 模拟题 面向对象程序设计思想的主要特征不包括:

{{ select(4) }}

  • 封装性
  • 多态性
  • 继承性
  • 功能分解,逐步求精
  1. 模拟题 下列有关C++类的说法中,不正确的是:

{{ select(5) }}

  • 类是一种用户自定义的数据类型
  • 只有类中的成员函数或类的友元函数才能存取类中的私有成员
  • 在类中,如果不做特别说明,所有成员的访问权限均为私有的
  • 在类中,如果不做特别说明,所有成员的访问权限均为公用的
  1. 模拟题 下面说法中,正确的是:

{{ select(6) }}

  • 一个类只能定义一个构造函数,但可以定义多个析构函数
  • 一个类只能定义一个析构函数,但可以定义多个构造函数
  • 构造函数与析构函数同名,只要名字前加了一个求反符号(~)
  • 构造函数可以指定返回类型,而析构函数不能指定任何返回类型,即使是void类型也不可以