2022华南师范大学C++程序设计(918)硕士研究生考试最后提分tips第三期

2022华南师范大学C++程序设计(918)硕士研究生考试最后提分tips第三期

前言

最近我也是背肖四背的头疼,给大家说的简答题总结一直没来得及做,距离考试不到几天了,最后提分tips系列也差不多准备完期了,至于会不会有第四期,那就要看我背肖四的情况了,在时间允许的情况下,我会在考试24号晚上七点前把最后一期发上来,大家25号考完英语后可以留意一下,当然如果没有发的话,这就是最后一期了,愿大家都能上岸,我们研究生见。

近四年问答题

21年:

1、什么是模板函数?模板函数有什么作用?

2、什么情况下必须定义自己的复制构造函数?

3、为什么要定义虚析构函数?

20年:

1.函数原型声明和函数定义说明

2.什么情况下必须定义自己的复制构造函数?

3.抽象类是什么,抽象类的作用是什么,抽象类的实质限制

19年:

1.请说明注释的作用?注释有几种?区别分别是什么?

2.请说明析构函数和构造函数的作用

3.请说明多态性和虚函数的作用

18年:

1、解释构造函数、析构函数之类的

2、解释三种继承方式

3、解释C++里面的多态,如何实现多态

总结

年份 考点
21年 模板函数,复制构造函数,虚析构函数
20年 函数原型声明和函数定义,复制构造函数,抽象类
19年 注释,析构函数和构造函数,多态性和虚函数
18年 构造函数、析构函数,三种继承方式,多态

**不难看出,命题老师的特点就是两热一冷的策略,其中贯穿四年的热考点构造函数析构函数,其次就是虚函数,而一冷就是其它考点,一般就考一次,像注释,模板等等,所以不难猜出今年的命题也是有两道题考点属于构造函数析构函数,以及虚函数,如果大家对专业课要求不是那么高的话完全可以就复习构造析构和虚函数,另外一个冷考点会就会,不会就不会好了,如果你要求比较高,其实不会一个简答题也不影响你考140。**下面就对考点进行归纳梳理。

热门考点

构造函数

目的:为了某个类的对象赋初值

特质:

  • 1.它不是由用户程序调用的,而是由系统在定义对象时自动调。2.所以构造函数名字必须与类名相同。
  • 1.系统在定义对象时自动调,所以程序不会检查该函数的返回值。2.构造函数不能指定返回值,void也不行
  • 1.每种赋初值方法对应一个构造函数。2.构造函数可以重载。3.定义对象时,系统根据给出的初值选择相应的构造函数。4.不带参数的构造函数称为默认构造函数。5.一个类通常应该有一个默认的构造函数(要没有,会自动生成一个函数体为空的构造函数,此时对象的所有数据成员的初值都为随机值)

构造函数的初始化列表:1.位于函数头和函数体之间。2.它以一个冒号开头,接着是一个以逗号分隔的数据成员列表,每个数据成员的后面跟着一个放在圆括号中的对应于该数据成员的构造函数的实际参数表。

DoubleArray(int lh,int rh):low(lh),high(rh){}

重点:对象的构造过程

构造一个对象由两个阶段组成:

1.首先按照数据成员的定义次序依次构造每个数据成员,执行每个数据成员对应类的构造函数。

2.然后执行当前类的构造函数为数据成员赋初值。

(初始化列表的好处)

3.如果指导了初始化列表,则可以使数据成员的初始化和赋初值同时进行。

4.采用初始化列表可以提高构造函数的效率,(使数据成员在构造的同时完成初值的设置)

(必须用初始化列表)

5.当数据成员是某个类的对象时,必须用初始化列表赋初值。类似下面这个Derived的构造函数

image-20211219153942661

6.当类中包含一个常量数据成员,常量只能在定义时对它进行初始化,而不能对它赋值,所以必须使用初始化列表

重点:复制构造函数

定义:用一个同类对象的常量引用作为参数,它的原型:

类名(const 类名 &obj){};

每个类都会有复制构造函数,如果我们没有定义,编译器会自动生成一个。函数形式参数对象的数据成员值对应地赋值给正在创建的对象的数据成员,即生成一个与形式参数完全一样的一个对象。这个就叫默认的复制构造函数。

如果复制构造有指针进行复制时就需要自己定义复制构造函数,因为默认的复制构造函数会使两个指针指向同一个地址空间,对其中任何一个的修改都会变成对另一个的修改,而且在一个对象析构时,另一个对象也会丧失原有的地址空间。

复制构造函数被调用的三种情况分别是:

  1. 用一个对象初始化另一个对象时
  2. 当用对象作为函数参数传递时
  3. 当函数返回对象时

析构函数

目的:回收内存空间,避免造成内存泄露。

特质:

  • 是系统在对象生命周期结束时自动调用的
  • 没有参数也没有返回值
  • 每个类必须有析构函数,没有的话,编译器会自动生成一个默认析构函数,函数体为空

虚析构函数:后面虚函数讲

虚函数

多态性

编译时的多态性:运算符重载,函数重载

运行时的多态性:虚函数,基类指针

当基类的指针调用该虚函数时,首先会到派生类中去看一看这个函数有没有被重新定义。如果派生类重新定义了这个函数,则执行派生类中的函数,否则执行基类的函数。

如果从该基类派生出多个派生类时,每个派生类都可以重新定义这个虚函数。当基类的指针指向不同的派生类的对象时,就会调用不同的函数,这样就实现了多态性。

是不是有点蒙,但是配合下面这个运行结果多读几遍这段话,你就可以理解了

image-20211219162113144

虚函数的特征:

  • 函数原型声明前加上virtual关键字
  • 在派生类中重新定义时,它的函数原型(包括返回类型,函数名,参数个数和参数类型)必须与基类中的虚函数完全相同,否则编译器会认为派生类有两个重载函数
  • 派生类在对虚函数重定义时,关键字virtual可以写也可以不写。

重点:虚析构函数

目的:回收内存空间,避免造成内存泄露。

这不是析构函数的目的吗?那为啥要加虚字呢?

问题就在于:

如果派生类新增加的数据成员中含有指针,指向动态申请的内存,那么派生类必须定义析构函数来释放这部分空间。

如果派生类的对象是通过基类的指针操作的,则基类指针会找到基类的析构函数,执行基类的析构函数。

但是此时派生类动态申请的空间没有释放,要释放这块空间必须执行派生类的析构函数。

所以可以把基类的析构函数定义为虚函数。

当析构基类指针指向派生类的对象时,会先找到基类的析构函数。

这时由于基类的析构函数是虚函数,又会找到派生类的析构函数,执行派生类的析构函数。

当派生类的析构函数在执行时会自动调用基类的析构函数,所以基类和派生类的析构函数都被执行了。

以上内容请一句一句理解

纯虚函数:

目的:避免写一个无用的函数体

定义:一个在基类中声明的虚函数。

virtual 返回类型 函数名(参数表)=0;

抽象类

定义:如果一个类至少含有一个纯虚函数,则被称为抽象类

特征:

  • 无法定义抽象类的对象
  • 可以定义指向抽象类的指针,它的作用是指向派生类对象,以实现多态性。
  • 如果抽象类的派生类没有重新定义此纯虚函数,只是基础了基类的虚函数,那么派生类仍然是一个抽象类

抽象类的作用:

保证进入继承层次的每个类都具有纯虚函数所要求的行为。

这保证了围绕这个层次所建立起来的类都具有抽象类规定的行为。

保证了软件系统的正常运行。

押题

1.构造函数为什么要有初始化列表?

2.试说明虚函数和纯虚函数有什么区别?

3.下标运算符为什么要重载成成员函数?下标运算符重载函数为什么要用引用返回?

最后三天背诵计划(这里起码有二十分,背了就有分)

第一天

【1】用 struct 定义类型与用 class 定义类型有什么区别?

【解】在结构体中,缺省的访问特性是公有的。在类中,缺省的访问特性是私有的。

【2】构造函数和析构函数的作用是什么?它们各有什么特征?

【解】构造函数是在对象定义时自动执行,为对象赋初值。析构函数是对象销毁时自动调用, 做一些善后工作。构造函数的名字就是类名,析构函数的名字是波浪号加类名。构造函数和析构函数都不需要写函数的返回类型。对象可能有不同的构造方法,所以类可以有一组重载的构造函数,但析构函数只能有一个。构造函数还可以有一个初始化列表。

【3】友元的作用是什么?

【解】使全局函数或其他类的成员函数、甚至是某个类定义所有的成员函数可以直接访问当前类的私有成员。

【4】静态数据成员有什么特征?有什么用途?

【解】不管这个类有多少个对象,静态数据成员都只有一份拷贝。静态数据成员一般用来保存整个类所有对象共享的信息。

【5】在定义一个类时,哪些部分应放在头文件(.h文件)中,哪些部分应放在实现文件(.cpp文件)中?

【解】类的定义放在头文件中,类中成员函数的实现放在实现文件中。

【6】什么情况下类必须定义自己的复制构造函数?

【解】如果类的数据成员中含有指针,而指针指向的是一个动态变量,必须自己定义复制构造函数。或对复制构造有其他特殊的要求也需要定义复制构造函数。

【7】什么样的成员函数应被说明为公有的?什么样的成员函数应被设为私有的?

【解】根据对象行为提取的成员函数应该设为公有的成员函数。公有函数的实现时分解出一些小函数通常被设计为私有的成员函数。

【8】常量数据成员和静态常量数据成员有什么区别?如何初始化常量数据成员?如何初始化静态常量数据成员?

【解】常量的数据成员指得是那些在对象生成时给定了初值,在整个对象的生命周期中,该数据成员的值是不能变的。常量数据成员的值必须在构造函数的初始化列表中进行初始化。静态的常量数据成员是整个类所有对象共享的一个常量。对整个类而言,不管定义了多少个对象,该成员永远只有一份拷贝。静态常量数据成员的值是在定义类时给定。

【9】什么是this指针?为什么要有this指针?

【解】每个对象包含两部分内容:数据成员和成员函数。不同的对象有不同的数据成员值,因此每个对象都拥有一块保存自己数据成员值的空间。但同一类的所有对象的成员函数的实现都是相同的,因此所有的对象共享了一份成员函数的代码。这又带来了另一个问题:成员函数中的涉及到的数据成员到底是哪个对象的数据成员?为此C++让每个成员函数都包含了一个隐含的参数this,该参数是一个指针,指向当前调用该成员函数的对象。成员函数中涉及的数据成员都是this指针指向的对象的数据成员。

【11】复制构造函数的参数为什么一定要用引用传递,而不能用值传递?

【解】值传递的参数在参数传递时有一个构造过程,即用实际参数的值构造形式参数,这个构造过程是由复制构造函数完成的。如果将复制构造函数的参数设计成值传递,会引起复制构造函数的递归调用。

【12】静态成员函数不能操作非静态的数据成员,那么非静态的成员函数能否操作静态的数据成员?为什么?

【解】因为静态成员函数没有隐含的this指针,所以不能够操作非静态的数据成员。静态的

数据成员是所有对象共享的数据成员,在逻辑上是属于每一个对象的,所以非静态的成员函数可以操作静态的数据成员。

【13】构造函数为什么要有初始化列表?

【解】构造函数的初始化列表可以将数据成员的构造和赋初值一起完成,提高对象构造的时间性能。除此之外,还有两种情况必须用初始化列表。第一种情况是数据成员中含有一些不能用赋值操作进行赋值的数据成员,例如常量数据成员或对象数据成员,这时必须在初始化列表中调用数据成员所属类型的构造函数来构造它们。第二种情况是在用派生的方法定义一个类时,派生类对象中的基类部分必须在构造函数的初始化列表中调用基类的构造函数完成。

第二天

【1】什么是组合?什么是继承?is-a的关系用哪种方式解决?has-a的关系用哪种方法解决?

【解】组合是将某个类的对象作为当前正在定义的类的数据成员,反映的是has-a的关系。继承是在一个类的基础上,通过增加数据成员或成员函数而得到一个功能更强大的类,反映的是is-a的关系。

【2】protected成员有什么样的访问特性?为什么要引入protected的访问特性?

【解】protected成员是允许派生类的成员函数可以访问的私有成员。可以提高派生类成员函数的效率。

【4】什么是抽象类?定义抽象类有什么意义?抽象类在使用上有什么限制?

【解】包含有纯虚函数的类称为抽象类。定义抽象类的主要用途是规范从这个抽象类派生的这些类的行为。在使用时,不能定义抽象类的对象,只能定义抽象类的指针。

【5】为什么要定义虚析构函数?

【解】将析构函数定义成虚函数可以防止内存泄漏。

【6】试说明派生类对象的构造和析构次序。

【解】构造时,先执行基类的构造函数,再执行派生类自己的构造函数。析构时,先执行派生类的析构函数,再执行基类的析构函数。

【7】试说明虚函数和纯虚函数有什么区别。

【解】虚函数有函数体,可以执行,也可以作为实现多态性的一种手段。而纯虚函数没有函数体,是不可以执行的。

【8】基类指针可以指向派生类的对象,为什么派生类的指针不能指向基类对象?

【解】由于派生类对象中包含了一个基类对象,当基类指针指向派生类对象时,通过基类指针可访问派生类中的基类部分。但如果用一个派生类指针指向基类对象,通过派生类指针访问派生类新增加的成员时,将无法找到这些成员。

【9】多态性是如何实现程序的可扩展性?

【解】派生类是一类特殊的基类,例如本科生、硕士生和博士生都是从学生类派生的。由于所有学生都要写论文,所以基类(学生类)中有一个“写论文”的虚函数。但每类学生写论文的要求是不一样的,因此在本科生、硕士生和博士生类中都有一个对应于虚函数的“写论文”函数。当需要向所有学生布置写论文的任务时,可以用一个学生类的指针遍历所有的学生。由于多态性,每类学生执行的是自己类新增的“写论文”函数,按照自己类规定的要求写论文。如果学校决定要招收工程硕士,那么系统中必须有一个“工程硕士”的类。工程硕士也是一类学生,所以也从学生类派生。工程硕士也要写论文,论文要求和其他几类学生不同,所以工程硕士类也要有一个“写论文”的函数。如果建好了工程硕士这个类,向全校学生布置写论文的工作流程还和以前一样。由此可见,当扩展系统时,只需要增加一些新的类,而主程序不变。

【10】如果一个派生类新增加的数据成员中有一个对象成员,试描述派生类的构造过程。

【解】构造派生类对象时,先调用基类的构造函数,再调用对象成员的构造函数,最后执行派生类的构造函数。

第三天

【1】重载后的运算符的优先级和结合性与用于内置类型时有何区别?

【解】与内置类型完全一样。

【3】如何区分++和–的前缀用法和后缀用法的重载函数?

【解】后缀++的重载函数中增加了第二个参数:一个整型的参数。这个参数只是为了区分两个函数,它的值没有任何意义。当程序中出现前缀++时,编译器调用不带整型参数的operator++函数。如果是后缀的++,则调用带整型参数的operator++函数。–重载也是如此。

【4】为什么要使用运算符重载?

【解】运算符重载可以使内置的运算符用于类的对象,使C++的功能得到了扩展。

【5】如果类的设计者在定义一个类时没有定义任何成员函数,那么这个类有几个成员函数?

【解】四个函数:默认的构造函数、默认的复制构造函数、析构函数和赋值运算符重载函数。

【6】如何实现类类型对象到内置类型对象的转换?如何实现内置类型到类类型的转换?

【解】内置类型到类类型的转换是通过构造函数。如果类有一个只带一个参数的构造函数,则可以实现参数类型到类类型的隐式转换。类类型到内置类型或其他类类型的转换必须通过类型转换函数。

【7】如何禁止内置类型到类类型的自动转换?

【解】在构造函数原型前加一个保留词explicit。

【8】下标运算符为什么要重载成成员函数?下标运算符重载函数为什么要用引用返回?

【解】下标运算符的第一个运算数是数组名,即当前类的对象。将下标运算符重载成成员函数时,编译器会将程序中诸如a[i]的下标变量的引用改为a.operator。如果a不是当前类的对象,编译器就会报错。下标变量是左值,所以必须用引用返回。

【9】如何禁止同类对象之间的相互赋值?

【解】将赋值运算符重载函数设为类的私有成员函数就可以了。

本图文内容来源于网友网络收集整理提供,作为学习参考使用,版权属于原作者。
THE END
分享
二维码
< <上一篇
下一篇>>