文章目录
- 前言
- 一、多态的常见选择
- 二、多态的常见问答
- 总结
前言
多态是C++的一大疑难杂症,有很多细枝末节的东西非常繁琐,这里搜集了一些常见的选择与问答。可以为大家带来帮助理解多态
一、多态的常见选择
- 下面哪种面向对象的方法可以让你变得富有( )
A: 继承 B: 封装 C: 多态 D: 抽象
解析:答案是继承,继承可以使得该类不需要写某些成员就可以去使用他们。从现实世界的角度理解,也是继承家业可以变得更加富有
- ( )是面向对象程序设计语言中的一种机制。这种机制实现了方法的定义与具体的对象无关,而对方法的调用则可以关联于具体的对象。
A: 继承 B: 模板 C: 对象的自身引用 D: 动态绑定
解析:方法就是函数,言外之意就是函数的定义与具体的对象没有太大的关系。对函数的调用是与具体的对象的有较大的关系。那么这不就是多态吗。而多态可以分为静态多态与动态多态,或者称为静态绑定与动态绑定。静态绑定有模板,运算符重载。动态绑定就是我们常见的虚函数重写实现的多态。这里显然是动态绑定
- 面向对象设计中的继承和组合,下面说法错误的是?()
A:继承允许我们覆盖重写父类的实现细节,父类的实现对于子类是可见的,是一种静态复用,也称为白盒复用
B:组合的对象不需要关心各自的实现细节,之间的关系是在运行时候才确定的,是一种动态复用,也称为黑盒复用
C:优先使用继承,而不是组合,是面向对象设计的第二原则
D:继承可以使子类能自动继承父类的接口,但在设计模式中认为这是一种破坏了父类的封装性的表现
解析:这道题显然选则C,应该是优先使用组合。
- 以下关于纯虚函数的说法,正确的是( )
A:声明纯虚函数的类不能实例化对象 B:声明纯虚函数的类是虚基类
C:子类必须实现基类的纯虚函数 D:纯虚函数必须是空函数
解析:这道题显然选择A,声明纯虚函数的类肯定不能实例化出对象
- 关于虚函数的描述正确的是( )
A:派生类的虚函数与基类的虚函数具有不同的参数个数和类型
B:内联函数不能是虚函数
C:派生类必须重新定义基类的虚函数
D:虚函数可以是一个static型的函数
解析:这道题选择的是B。对于A而言,其实描述不太准确,它应该问的是虚函数的重写,而重写必须满足虚函数+三同。对于B,虚函数确实不能是内联函数。C虚函数可以不用重写。D、虚函数不可以加上static修饰。
- 关于虚表说法正确的是( )
A:一个类只能有一张虚表
B:基类中有虚函数,如果子类中没有重写基类的虚函数,此时子类与基类共用同一张虚表
C:虚表是在运行期间动态生成的
D:一个类的不同对象共享该类的虚表
解析:这道题选择的是D,对于A而言,多继承存在两张以上的虚表。对于B,不是共用一张的。对于C,虚表是在编译阶段生成的。
- 假设A类中有虚函数,B继承自A,B重写A中的虚函数,也没有定义任何虚函数,则( )
A:A类对象的前4个字节存储虚表地址,B类对象前4个字节不是虚表地址
B:A类对象和B类对象前4个字节存储的都是虚基表的地址
C:A类对象和B类对象前4个字节存储的虚表地址相同
D:A类和B类虚表中虚函数个数相同,但A类和B类使用的不是同一张虚表
解析:选D,A类和B类的前四个字节存储的都是虚表地址,且虚表中的虚函数相同,但A类和B类使用的不是同一张虚表
二、多态的常见问答
- 什么是多态?
多态分为两种,一种是静态的多态,一种是动态的多态。静态的多态如函数模板,运算符重载,运算符重载就是编译器通过函数名修饰规则等方式实现的。动态的多态需要继承中虚函数的重写,父类的指针或引用去调用该虚函数,这两个条件才能达成。
无论是静态的多态还是动态的多态,都是更方便和灵活多种形态的调用。
- 什么是重载、重写(覆盖)、重定义(隐藏)?
- 多态的实现原理?
静态的多态是通过函数名修饰规则来实现的,而动态的多态是通过虚函数表来实现的。
- inline函数可以是虚函数吗?
答:可以,不过编译器就忽略inline属性,这个函数就不再是inline,因为虚函数要放到虚表中去。内联函数本身并没有地址。虽然语法上可以通过,但是其本质并非将虚函数变成了内联。因为我们的这个inline的作用仅仅只是建议成为内联,具体是否为内联取决于编译器。而且我们不写inline,编译器也会自行判断是否需要为inline。
- 静态成员可以是虚函数吗?
答:不能,因为静态成员函数没有this指针,使用类型::成员函数的调用方式无法访问虚函数表,因为就没有对象,没有对象哪来的虚表,所以静态成员函数无法放进虚函数表。无法实现出多态,也就没有意义,所以语法会强制检查。
- 构造函数可以是虚函数吗?
答:不能,编译直接报错。因为对象中的虚函数表指针是在构造函数初始化列表阶段才初始化的。如果将构造函数变为了虚函数,那么就变成了先有鸡还是先有蛋的问题。因为只有对象初始化好了,才会有虚表。而此时我们将构造函数变成了虚函数,想要将他放入虚表。这就出现了先有鸡还是先有蛋的问题了。
- 析构函数可以是虚函数吗?什么场景下析构函数是虚函数?
答:可以,并且最好把基类的析构函数定义成虚函数。否则可能出现内存泄漏的问题
- 对象访问普通函数快还是虚函数更快?
答:首先如果是普通对象,是一样快的。如果是指针对象或者是引用对象,则调用的普通函数快,因为构成多态,运行时调用虚函数需要到虚函数表中去查找。
- 虚函数表是在什么阶段生成的,存在哪的?
答:虚函数表是在编译阶段就生成的,一般情况下存在代码段(常量区)的。
- C++菱形继承的问题?虚继承的原理?
答:数据冗余和二义性。原理是虚基表,存储偏移量。
- 什么是抽象类?抽象类的作用?
答:抽象类强制重写了虚函数,另外抽象类体现出了接口继承关系
总结
本文讲解了一些关于多态的常见面试题,希望能对读者带来帮助。