2021东南⼤学916复试553C++整理
问答题
1. ⽐较值传递和引⽤传递的相同点和不同点。
(1)值传递是指当发⽣函数调⽤时,给形参分配内存空间,并⽤实参来初始化形参(直接将实参的值传递给形参)。这⼀过程是参数值的单向传递过程,⼀旦形参获得了值便与实参脱离关系,此后⽆论形参发⽣了怎样的改变,都不会影响到实参。
(2)引⽤传递将引⽤作为形参,在执⾏主调函数中的调⽤语句时,系统⾃动⽤实参来初始化形参。这样形参就成为实参的⼀个别名,对形参的任何操作也就直接作⽤于实参。
2 什么叫内联函数?它有哪些特点?
1. 定义时使⽤关键字 inline 的函数叫做内联函数;编译器在编译时在调⽤处⽤函数体进⾏替换,节省了参数传递、控制转移等开销;
2. 内联函数体内不能有循环语句和 switch 语句;
3. 内联函数的定义必须出现在内联函数第⼀次被调⽤之前;对内联函数不能进⾏异常接⼝声明;
3 什么叫复制构造函数?复制构造函数何时被调⽤?
复制构造函数是⼀种特殊的构造函数,具有⼀般构造函数的所有特性,其形参是本类的 对象的引⽤ (const T &)。其作⽤是使⽤⼀个已经存在的对象(由复制构造函数的参数指定),去初始化同类的⼀个新对象。
(1) 当⽤类的⼀个对象去初始化该类的另⼀个对象时;
(2) 如果函数的形参是类的对象,调⽤函数时进⾏形参和实参结合时;
(3) 如果函数的返回值是类的对象,函数执⾏完成返回调⽤者时。
4、复制构造函数与赋值运算符(=)有何不同?
从概念上区分:复制构造函数是构造函数,⽽赋值操作符属于操作符重载范畴,它通常 是类的成员函数 从原型上来区分:
复制构造函数原型 ClassType(const ClassType &);⽆返回值;
赋值操作符原型 ClassType& operator=(const ClassType &);返回值为 ClassType 的引⽤,便于连续
赋 值操作 从使⽤的场合来区分:复制构造函数⽤于产⽣对象,它⽤于以下⼏个地⽅:函数参数为 类的值类型时、函数返回值为类类型时以及初始化语句
5 什么叫作⽤域?有哪⼏种类型的作⽤域?
作⽤域讨论的是标识符的有效范围,作⽤域是⼀个标识符在程序正⽂中有效的区域。
C++的作⽤域分为:函数原型作⽤域、函数作⽤域、⽂件作⽤域(全局作⽤域)、块作⽤ 域(局部作⽤域)、类作⽤域和名字空间作⽤域。
6 什么叫做可见性?可见性的⼀般规则是什么?
可见性是标识符是否可以引⽤的问题;
可见性的⼀般规则是:标识符要声明在前,引⽤在后,在同⼀作⽤域中,不能声明同名的标识符。
对于在不同的作⽤域声明的标识符,遵循的原则是:若有两个或多个具有包含关 系的作⽤域,外层声明的标识符如果在内层没有声明同名标识符时仍可见,如果内层声明了同名标识符则外层标识符不可见。
7 什么叫静态数据成员?他有何特点?
类的静态数据成员是类的数据成员的⼀种特例,采⽤ static 关键字来声明。对于类的普通数据成员,每⼀个类的对象都拥有⼀个拷贝,就是说每⼀个对象的同名数据成员可以分别存储不同的值,这也是保证对象拥有区别于其他对象的特征的需要,但是静态数据成员,每个类只要⼀个拷贝,由所有该类的对象共同维护和使⽤,这个共同维护,使⽤也就实现了同⼀类的不同对象之间的数据共享。
8 什么叫静态函数成员?他有何特点?
使⽤ static 关键字声明的函数成员是静态的,静态函数成员属于整个类,被同⼀个类的所有对象共同维护,为这些所有对象共享。
静态成员函数具有以下两个⽅⾯的好处:
⼀是由于静态成员函数只能直接访问同⼀个类的静态数据成员,可以保证不会对该类的其余数据成员造成负⾯影响;
⼆是同⼀个类只维护⼀个静态函数成员的拷贝,节约了系统的开销,提⾼ 程序的运⾏效率。
9 什么叫友元函数?什么叫友元类?
友元函数是使⽤关键字 friend 关键字声明的函数,它可以访问相应类的保护成员和私有成员。友元类是使⽤ friend 关键字声明的类,它的所有成员函数都是相应类的友元函数。
友元不可继承,没有传递性。
10 在函数内部定义的普通局部变量和静态局部变量在功能上有何不同?计算机底层对这两类变量做了怎样的不同处理导致了这种差异?
局部作⽤域中静态变量的特点是:它并不会随着每次函数调⽤⽽产⽣⼀个副本,也不会随着函数的返回⽽失效,定义时未指定初值的基本类型静态变量,会被以 0 值初始化;局部作⽤域的全局变量诞⽣于声明点,结束于声明所在的块执⾏完毕之时,并且不指定初值,意味初值不确定。
普通局部变量存放于栈区,超出作⽤域后,变量被撤销,其所占的内存也被回收;静态局部变量存放于静态数据存储区,全局可见,但是作⽤域是局部作⽤域,超出作⽤域后变量仍然存在。
11 引⽤和指针有何区别?何时只能使⽤指针⽽不能使⽤引⽤?
引⽤是⼀个别名,不能为 NULL 值,不能被重新分配;
指针是⼀个存放地址的变量。
当需要对变量重新赋以另外的地址或赋值为 NULL 时只能使⽤指针。const的作用
引⽤是⼀个变量的别名,本⾝不单独分配⾃⼰的内存空间,⽽指针有⾃⼰的内存空间。
12 ⽐较类的 3 种继承⽅式之间的差别?
1. 公有继承,使得基类 public(公有)和 protected(保护)成员的访问属性在派⽣类中不变,⽽基类 private(私有)成员不可访问。
2. 私有继承,使得基类 public(公有)和 protected(保护)成员都以 private(私有)成员⾝份出现在派⽣类中,⽽基类 private(私有)成员不
可访问。
3. 保护继承中,基类 public(公有)和 protected(保护)成员都以 protected(保护)成员⾝份出 现在派⽣类中,⽽基类 private(私有)成员
不可访问。
13 什么叫虚基类?有何作⽤?(菱形继承)
(1)当某类的部分或全部直接基类是从另⼀个基类派⽣⽽来,这些直接基类中,从上⼀级基类继承来的成员就拥有相同的名称,派⽣类的对象的这些同名成员在内存中同时拥有多个拷贝,我们可以使⽤作⽤域分辨符来唯⼀标识并分别访问它们。(解决⼆义性)我们也可以将直接基类的共同基类设置为
虚基类,这时从不同的路径继承过来的该类成员在内存中只拥有⼀个拷贝,这样就解决了同名成员的唯⼀标识问题。
(2)虚基类的声明是在派⽣类的定义过程,其语法格式为:
class 派⽣类名:virtual 继承⽅式 基类名
上述语句声明基类为派⽣类的虚基类,在多继承情况下,虚基类关键字的作⽤范围和继承⽅式关键字相同,只对紧跟其后的基类起作⽤。声明了虚基类之后,虚基类的成员在进⼀步派⽣过程中,和派⽣类⼀起维护⼀个内存数据拷贝。
虚基类就是为了解决多继承产⽣的⼆义性问题
14 组合与继承有什么共同点和差异?通过组合⽣成的类与被组合的类之间的逻辑关系是什么?继承呢?
(1)组合和继承它们都使得已有对象成为新对象的⼀部分,从⽽达到代码复⽤的⽬的。组合和继承其实反映了两种不同的对象关系。
(2)组合反映的是“有⼀个”(has-s)的关系,如果类 B 中存在⼀个类 A 的内嵌对象,表⽰的是每⼀个 B 类型的对象都“有⼀个”A 类型的对象,A 类型的对象与 B 类型的对象是部分整体 的关系。
(3)继承反映的是“是⼀个”(is-a)的关系,在“是⼀个”关系中,如果类 A 是类 B 的公有基类,那么这表⽰每⼀个 B 类型的对象
都“是⼀个”A 类型的对象,B 类型的对象与 A 类型的对象是特殊与⼀般的关系。
15 基类与派⽣类的对象,指针或引⽤之间,哪些情况下可以隐含转换,哪些情况下可以显⽰转换?在涉及多重继承或虚继承的情况下,在转换时会⾯临哪些新问题?
1. 派⽣类指针可以隐含转换为基类指针,⽽基类指针要想转换为派⽣类指针,则转换⼀定要显⽰地进⾏。因为从特殊的指针转换到⼀般
的指针时安全的,因此允许隐含转换;
2. 从⼀般的指针转换到特殊的指针是不安全的,因此只能显⽰地转换。基类对象⼀般⽆法被显式转换为派⽣类对象。
3. 在多重继承情况下,执⾏基类指针到派⽣类指针的显式转换时,有时需要将指针所存储的地址值进⾏调整后才能得到新指针的值。
(4)但是,如果 A 类型是 B 类型的虚基类,虽然 B 类型的指针可以隐含转换为 A 类型,但是 A 类型指针却⽆法通过 static_case 隐含转换为 B 类型的指针。
16 什么叫做多态性?在 C++种是如何实现多态的?
**多态是指同样的消息被不同类型的对象接收时导致完全不同的⾏为,是对类的特定成员函数的再抽象。
**C++⽀持重载多态,强制多态,包含多态和参数多态。
在基类中声明相应的函数为 virtual 型,然后在派⽣类中实现该函数,这样就可以通过基类指针调⽤派⽣类对象的函数,实现了运⾏时动态绑定,即多态的功能。
17 什么叫抽象类?抽象类有何作⽤?抽象类的派⽣类是否⼀定要给出纯虚函数的实现?
带有纯虚函数的类是抽象类。
其主要作⽤是通过它为⼀个类族建⽴⼀个公共的接⼝,使他们能够更有效地发挥多态特性。
抽象类声明了⼀个类族派⽣类的共同接⼝,⽽接⼝的完整实现,即纯虚函数的函数体,要由派⽣类⾃⼰定义。抽象类派⽣出新的类之后,如果派⽣类给出所有纯虚函数的函数实现,这个派⽣类就可以定义⾃⼰的对象,因⽽不再是抽象类;反 之,如果派⽣类没有给出全部纯虚函数的实现,此时的派⽣类仍然是⼀个抽象类。
18 在 C++中,能否声明虚构造函数?为什么?能否声明虚析构函数?有何⽤途?
(1)在 C++中,不能声明虚构造函数,多态是不同的对象对同⼀消息有不同的⾏为特性,虚函数作为运⾏过程中多态的基础,主要是针对对象的,⽽构造函数是在对象产⽣之前运⾏的,因此虚构造函数是没有意义的;
(2)可以声明虚析构函数,析构函数的功能是在该类对象消亡之前进⾏⼀些必要的清理⼯作, 如果⼀个类的析构函数是虚函数,那么,由它派⽣⽽来的所有⼦类的析构函数也是虚函数。
(3)析构函数设置为虚函数之后,在使⽤指针引⽤时可以动态联编,实现运⾏时的多态,保证使⽤基类的指针就能够调⽤适当的析构函数针对不同的对象进⾏清理⼯作。(虚析构函数可以解决以下问题:多态使⽤时,如果⼦类中有属性开辟到堆区,那么⽗类指针在释放时⽆法调⽤⼦类的析构代码)
19 什么叫做流?流的提取和插⼊是指什么?I/O 流在 C++中起着怎样的作⽤?
(1)流是⼀种抽象,它负责在数据的⽣产者和数据的消费者之间建⽴联系,并管理数据的流动,⼀般意义下的读操作在流数据抽象中被称为(从流中)提取,写操作被称为(向流中)插⼊。
(2)操作系统是将键盘、屏幕、打印机和通信端⼝作为扩充⽂件来处理的,I/O 流类就是 ⽤来与这些扩充⽂件进⾏交互,实现数据的输⼊与输出。
20 什么叫做异常?什么叫做异常处理?
(1)当⼀个函数在执⾏的过程中出现了⼀些不平常的情况,或运⾏结果⽆法定义的情况,使得操作不得不被中断时,我们说出现了异常。异常通常是⽤ throw 关键字产⽣的⼀个对象,⽤来表明出现了⼀些意外的情况。
(2)我们在设计程序时,就要充分考虑到各种意外情况,并给与恰当的处理。这就是我们所说的异常处理。
21 C++的异常处理机制有何优点?
C++的异常处理机制使得异常的引发和处理不必在同⼀函数中,这样底层的函数可以着重解决具体问题,⽽不必过多地考虑对异常的处理。上层调⽤者可以在适当的位置设计对不同类型异常的处理。
22 ⽐较函数重载和虚函数在概念和使⽤⽅式⽅⾯有什么区别?
(1)函数重载可以⽤于普通函数(⾮成员的函数)和类的成员函数,⽽虚函数只能⽤于类的成员函数。
(2)函数重载可以⽤于构造函数,⽽虚函数不能⽤于构造函数。
(3)如果对成员函数进⾏重载,则重载的函数与被重载的函数应当都是同⼀类中的成员函数,不能分属于两个不同继承层次的类。函数重载是横向的重载。
虚函数是对同⼀类族中的基类和派⽣类的同名函数的处理,即允许在派⽣类中对基类的成员函数重新定义。虚函数的作⽤是处理纵向的同名函数。
(4)重载的函数必须具有相同的函数名,但函数的参数个数和参数类型⼆者中⾄少有⼀样不同,否则在编译时⽆法区分它们。⽽虚函数则要求再同⼀类族中的所有虚函数不仅函数名相同,⽽且要求函数类型、函数的参数个数和参数类型都全部相同,否则就不是重定义了。也就不是虚函数了。
(5)函数重载是在程序编译阶段确定操作的对象的,属静态多态。虚函数是在程序运⾏阶段确定操作的对象的,属动态多态。
23 ⽐较 class 和 struct 结构体的异同
不同之处:
(1)默认成员访问权限不同,struct 默认是 public,⽽ class 默认是 private。
(2)默认继承⽅式不同,struct 默认是 public,⽽ class 默认是 private。
(3)在定义模板参数时可以⽤ class 但不能⽤ struct。
相同之处在于:
都可以包含成员函数,都可以实现继承,都可以实现多态。
24 浅拷贝和深拷贝的区别?
在某些情况下,类内的成员变量需要动态开辟堆内存,如果实⾏按位拷贝,就可能会出现两个对象⾥⾯的成员变量指针指向同⼀块内存区域。当回收其中⼀个对象时,该对象成员变量所指向的内存区域也将回收,会导致另⼀个对象存在野指针的情况。⾮常危险。(堆区资源重复释放)
深拷贝和浅拷贝可以简单理解为:如果⼀个类拥有资源,当这个类的对象发⽣复制过程的时候,资源重新分配,这个过程就是深拷贝,反之,没有重新分配资源,就是浅拷贝。
25 const 和 static 作⽤
(1)const 作⽤:
1. 定义 const 常量,具有不可变性,保护被修饰的东西。防⽌意外修改,增强程序的健壮性。
2. 便于类型检查,使编译器对处理内容有更多的了解。
3. 可以避免意义模糊的数字出现,也便于进⾏参数的修改。同宏定义⼀样,可以做到不变则以,⼀变都变。const 定义的常量在程序运
⾏过程中只有⼀份拷贝,⽽宏定义却⼜若⼲份拷贝。
(2)static:
作为类的静态数据成员:被类的所有对象共同拥有,在内存中只有⼀份拷贝。在类内声明,在类外初始化。
1. 在全局变量前加上 static 关键字,该变量被定义为⼀个静态全局变量,
特点:
a) 变量在全局数据区分配内存
b) 如果不显⽰初始化,则隐式的初始化为 0
c) 作⽤域仅限于本⽂件内
1. 在局部变量前加 static 关键字,该变量被定义为静态局部变量,
特点:
a) 在全局数据区分配内存
b) 如果不显⽰初始化,则隐式的初始化为 0

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。