1.面试官:在使用继承时需要注意哪些问题?
应聘者:在使用继承时需要注意以下内容。
(1)父类的构造函数和析构函数是不会被继承的,需要重写派生类的构造函数和析构函数。
(2)派生类的成员数据中有来自父类的成员数据,因此在写派生类的构造函数的时候需要调用其父类的构造函数。
(3)如果派生类的成员中有成员对象,那么也需要用成员对象名来进行初始化。
(4)派生类构造函数、析构函数的调用顺序如下:
①构造函数中首先调用各个直接基类的构造函数,之后再调用成员对象的构造函数,最后才是新增成员的初始化。
②对于多继承有多个基类,那么其构造函数的调用顺序是按被继承时的声明顺序,从左到右一次调用,与初始化表的顺序无关。
③对于成员对象的初始化也是一样,与它们的声明顺序有关,和构造函数中的初始化表的顺序无关。
④如果没有进行显示的调用,那么会调用其默认的构造函数。
⑤子类的复制构造函数也要为各个直接基类的复制构造函数传递参数。
⑥在派生类的析构函数中不会显示调用基类的析构函数,系统会自动隐式调用,调用顺序和构造函数的调用顺序正好相反,先构造的后析构。
2.面试官:C++多态是如何实现的,及其原理是什么?
应聘者:C++的多态性用一句话概括就是:在基类的函数前加上virtual关键字,在派生类中重写该函数,运行时将会根据对象的实际类型来调用相应的函数。如果对象类型是派生类,就调用派生类的函数;如果对象类型是基类,就调用基类的函数。
(1)用virtual关键字声明的函数叫作虚函数,虚函数肯定是类的成员函数。
(2)存在虚函数的类都有一个一维的虚函数表叫作虚表,类的对象有一个指向虚表开始的虚指针。虚表是和类对应的,虚表指针是和对象对应的。
(3)多态性是一个接口多种实现,是面向对象的核心,分为类的多态性和函数的多态性。
(4)多态用虚函数来实现,结合动态绑定。
(5)纯虚函数是虚函数再加上“= 0”。
(6)抽象类是指包括至少一个纯虚函数的类。纯虚函数:“virtual void fun()=0;”即抽象类!必须在子类实现这个函数,即先有名称,没有内容,在派生类中实现内容。
3.面试官:运算符重载作为类成员函数和友元函数之间的区别?
应聘者:在多数情况下,将运算符重载为类的成员函数和类的友元函数都是可以的。但成员函数运算符与友元函数运算符也具有各自的一些特点:
(1)一般情况下,单目运算符最好重载为类的成员函数;双目运算符则最好重载为类的友元函数。
(2)以下一些双目运算符不能重载为类的友元函数:=、()、[]、->。
(3)类型转换函数只能定义为一个类的成员函数而不能定义为类的友元函数。
(4)若一个运算符的操作需要修改对象的状态,选择重载为成员函数较好。
(5)若运算符所需的操作数希望有隐式类型转换,则只能选用友元函数。
(6)当运算符函数是一个成员函数时,最左边的操作数(或者只有最左边的操作数)必须是运算符类的一个类对象(或者是对该类对象的引用)。如果左边的操作数必须是一个不同类的对象,或者是一个内部类型的对象,该运算符函数必须作为一个友元函数来实现。
(7)当需要重载运算符具有可交换性时,选择重载为友元函数。
4.面试官:什么是I/O流?
应聘者:在C++中,将数据从一个对象到另一个对象的流动抽象为“流”(stream)。当输入时,所输入的信息是从键盘对应的缓冲区中流入正在运行的程序的缓冲区,这些输入的信息称为“输入流”,该操作称为“读操作”。当输出时,数据从程序流向屏幕或磁盘文件,称为“输出流”,该操作称为“写操作”。
5.面试官:get()和getline()有什么区别?
应聘者:get()函数每次只能读取一个字符,而getline()函数可以读取整行数据,包括空白在内。
6.面试官:C++为什么不使用标准I/O函数?
应聘者:C语言中提供两个标准I/O函数,格式分别如下:
printf(格式控制符,输出变量1,输出变量2...);
scanf(格式控制符,输出变量1的地址,输出变量2的地址...);
两个函数都用格式控制字符串,在使用时都要求后面的变量个数和变量类型都要与前面字符串中给出的格式符的格式对应一致。但由于程序员的疏忽,这种不匹配时有发生,从而产生错误的结果,甚至使系统不能工作。
而且这两个I/O函数不具有可扩充性。格式控制字符串中,所有控制符只适用于内部定义数据类型。C语言的I/O函数没有提供对用户定义对象的支持。因此,C语言的I/O函数没有灵活性和可扩充性,不能针对实际的类对象产生重载函数。