|
|
|
|
移动端

1.16.4 虚函数

《程序员面试笔试真题与解析》本书针对当前各大 IT企业面试笔试中特性与侧重点,精心挑选了 3年以来近百家典型 IT企业的面试笔试真题,这些企业涉及业务包括系统软件、搜索引擎、电子商务、手机 APP、安全关键软件等,面试笔试真题非常具有代表性与参考性。本节为大家介绍虚函数。

作者:猿媛之家来源:机械工业出版社|2017-12-06 18:50

有奖调研 | 1TB硬盘等你拿 AI+区块链的发展趋势及应用调研


1.16.4 虚函数

【真题 263】有以下代码:

  1. class parent  
  2. {  
  3. public:  
  4. virtual void output();  
  5. };  
  6. void parent::output()  
  7. {  
  8. printf("parent");  
  9. }  
  10. class son : public parent  
  11. {  
  12. public:  
  13. virtual void output();  
  14. };  
  15. void son::output()  
  16. {  
  17. printf("son");  

则以下程序段:

  1. son s;  
  2. ::memset(&s , 0 , sizeof(s));  
  3. parent& p = s;  
  4. p.output(); 

的执行结果是( )。

A.parent  B.son   C.sonparent  D.没有输出结果,程序运行出错

答案:D。

被 virtual关键字修饰的成员函数,就是虚函数,虚函数的作用是实现多态性( Polymorphism)。当类中定义了虚函数后,在实例化的对象中会有一个额外的指针 vptr指向一个虚函数表 vtable,虚函数表中存放了实际调用函数的地址。

对于本题而言,由于 output是一个虚函数,在调用的时候,需要首先根据 vptr找到 vtable,然后在 vtable中查找实际要调用的 output函数的地址。但是,调用 memset函数会把 vptr指针的值改为 0,因此,通过 vptr无法找到 vtable,程序运行会出错。所以,选项 D正确。

【真题 264】下列关于虚函数的描述中,正确的是()。

A.在构造函数中调用类自己的虚函数,虚函数的动态绑定机制还会生效

B.在析构函数中调用类自己的虚函数,虚函数的动态绑定机制还会生效

C.静态函数不可以是虚函数

D.虚函数可以声明为 inline 答案:B、C。本题中,对于选项 A,在类的继承中,当实例化子类的对象时,会首先调用基类的构造函数,如果

在构造函数中调用了虚函数,此时由于子类还没有完成初始化,不会去调用子类的方法,所以,在构造函数中调用虚函数,动态绑定机制不会生效。因此,选项 A错误。

对于选项 B,在 C++语言中,经常会把析构函数定义成虚函数,为了防止在实现多态的情况下,当用基类操作派生类,在析构时防止只析构基类而不析构派生类的状况发生。因此,在析构函数中,虚函数的动态绑定机制会生效。所以,选项 B正确。

对于选项 C,虚函数是为了多态设计的,静态成员函数独立于对象存在,无法实现多态,而且静态成员函数没有 this指针,无法找到虚函数表,所以,不能将静态函数设计为虚函数。因此,选项 C正确。

对于选项 D,函数的 inline属性是在编译时确定的,是静态行为。而 virtual的性质是在运行时确定的,是动态行为。它们是矛盾的,二者不能同时存在。因此,选项 D错误。所以,本题的答案为 B、C。

【真题 265】关于 virtual void Draw()=0,下面说法正确的有()个。

(1)它是纯虚函数

(2)它在定义它的类中不能实现

(3)定义它的类不可实例化

(4)如果一个类要继承一个 ADT类,必须要实现其中的所有纯虚函数

A.1 B.2 C.3 D.4 答案:C。本题中,(1)、(2)、(3)的描述是正确的,(4)的描述是错误的,如果一个类要继承一个

ADT(Abstract Data Type,抽象数据类型)类,可以不实现其中的所有纯虚函数,派生之后的类仍旧作为一个抽象类。所以,选项 C正确。

【真题 266】什么函数不能声明为虚函数?答案:常见的不能声明为虚函数的有普通函数(非成员函数)、静态成员函数、内联成员函数、构造函数和友元函数。以下将分别对这几种情况进行分析。

1)普通函数(非成员函数)只能 overload(重载),不能被 override(覆盖),不能被声明为虚函数,因此,编译器会在编译时绑定函数。

2)静态成员函数不能是虚函数,因为静态成员函数对于每个类来说只有一份代码,所有的对象都共享这一份代码,它不归某个对象所有,所以,它也没有动态绑定的必要性。

3)内联成员函数不能是虚函数,因为内联函数本身就是为了在代码中直接展开,减少函数调用花费的代价而设立的,而虚函数是为了在继承后对象能够准确地执行自己的动作,这是不可能统一的。再说,inline函数在编译时被展开,虚函数在运行时才能动态地绑定函数。

4)构造函数之所以不能是虚函数,因为构造函数本来是为了明确初始化对象成员才产生的,然而虚函数主要是为了在不完全了解细节的情况下也能正确处理对象。另外,虚函数是在不同类型的对象产生不同的动作,现在对象还没有产生,如何使用虚函数来完成你想完成的动作?

5)友元函数。

C++语言不支持友元函数的继承,对于没有继承特性的函数没有虚函数的说法。友元函数不属于类的成员函数,不能被继承。所以,友元函数不能是虚函数。

【真题 267】如何定义纯虚函数?

答案:virtual void f()=0,纯虚函数是接口,子类必须要实现。

【真题 268】有如下代码:

  1. class ClassA  
  2. {  
  3. public:  
  4. virtual ~ ClassA(){};  
  5. virtual void FunctionA(){};  
  6. };  
  7. class ClassB  
  8. {  
  9. public:  
  10. virtual void FunctionB(){};  
  11. };  
  12. class ClassC : public ClassA,public ClassB  
  13. {  
  14. public:  
  15. };  
  16. ClassC aObject;  
  17. ClassA* pA=&aObject;  
  18. ClassB* pB=&aObject;  
  19. ClassC* pC=&aObject; 

下面语句是不安全的是()。

A.delete pA B.delete pB C.delete pC D.以上都正确答案:A、B、C、D。

本题中,由于 pA、pB、pC都不是动态分配的,因此,它们都是不安全的,运行时都会出错。所以,选项 A、选项 B、选项 C与选项 D错误。

【真题 269】下列关于多态性的说法中,不正确的是()。

A.多态性是指同名函数对应多种不同的实现 B.重载方式仅有函数重载

C.重载方式包含函数重载和运算符重载 D.多态性表现为静态和动态两种方式

答案:B。

重载方式有函数重载和运算符重载。所以,选项 B错误。

【真题 270】假设 A为抽象类,下列声明正确的是()。

A.int fun(A); B.A Obj; C.A fun(int); D.A *p;答案:D。在 C++语言中,含有纯虚函数的类称为抽象类,它不能生成对象。抽象类不能初始化,不能当作返

回值,不能当作参数,可以作为指针变量,因为此时还没有初始化。所以,选项 A、选项 B与选项 C错误,选项 D正确。

【真题 271】下面关于虚函数和函数重载的叙述中,不正确的是()。

A.虚函数不是类的成员函数

B.虚函数实现了 C++的多态性

C.函数重载允许非成员函数,而虚函数则不行

D.函数重载的调用根据参数的个数、序列来确定,而虚函数依据对象确定

答案:A。

喜欢的朋友可以添加我们的微信账号:

51CTO读书频道二维码


51CTO读书频道活动讨论群:365934973

【责任编辑:book TEL:(010)68476606】

回书目   上一节   下一节
点赞 0
分享:
大家都在看
猜你喜欢

读 书 +更多

网络工程师必读——网络系统设计

本书是一本真正意义上的网络系统设计图书,从网络系统设计角度全面介绍了整个网络系统设计的思路和方法,而不是像传统网络集成类图书那样主...

订阅51CTO邮刊

点击这里查看样刊

订阅51CTO邮刊