文章目录
- 1. 选择题
- 2. 问答题
- 2.1 什么是多态?
- 2.2 什么是重载、重写(覆盖)、重定义(隐藏)?
- 2.3 多态的实现原理?
- 2.4 inline函数可以是虚函数吗?
- 2.5 静态成员可以是虚函数吗?
- 2.6 构造函数可以是虚函数吗?
- 2.7 析构函数可以是虚函数吗?什么场景下析构函数要搞成虚函数?
- 2.8 对象调普通函数快还是虚函数更快?
- 2.9 虚函数表是在什么阶段生成的,存在哪的?
- 2.10 C++菱形继承的问题?虚继承的原理?
- 2.11 什么是抽象类?抽象类的作用?
之前的几篇文章我们学习了C++中的多态和继承,这篇文章给大家整理一下继承和多态相关的常考题目,供大家学习。
当然里面有些问题都是之前文章里面详细讲解过的,文章链接放在这里,大家可以参考:
继承
复杂的菱形继承 及 菱形虚拟继承的底层原理
多态
详解多态的底层原理
1. 选择题
- 下面哪种面向对象的方法可以让你变得富有( )
A: 继承 B: 封装 C: 多态 D: 抽象
答案:A
- ( )是面向对象程序设计语言中的一种机制。这种机制实现了方法的定义与具体的对象无关,而对方法的调用则可以关联于具体的对象。
A: 继承 B: 模板 C: 对象的自身引用 D: 动态绑定
答案:D
- 面向对象设计中的继承和组合,下面说法错误的是?()
A:继承允许我们覆盖重写父类的实现细节,父类的实现对于子类是可见的,是一种静态复用,也称为白盒复用
B:组合的对象不需要关心各自的实现细节,之间的关系是在运行时候才确定的,是一种动态复用,也称为黑盒复用
C:优先使用继承,而不是组合,是面向对象设计的第二原则
D:继承可以使子类能自动继承父类的接口,但在设计模式中认为这是一种破坏了父类的封装性的表现
答案:C(之前的文章里也有相关的讲解)
4. 以下关于纯虚函数的说法,正确的是( )
A:声明纯虚函数的类不能实例化对象 B:声明纯虚函数的类是虚基类
C:子类必须实现基类的纯虚函数 D:纯虚函数必须是空函数
答案:A
- 关于虚函数的描述正确的是( )
A:派生类的虚函数与基类的虚函数具有不同的参数个数和类型
B:内联函数不能是虚函数(可以认为语法上可以)
C:派生类必须重新定义基类的虚函数
D:虚函数可以是一个static型的函数
答案:B(下面问答题有讲)
内联函数语法上可以是虚函数,但是编译器就忽略inline这个属性,这个函数本质就不再是inline,因为虚函数要产生地址放到虚表中去。
- 关于虚表说法正确的是( )
A:一个类只能有一张虚表
B:基类中有虚函数,如果子类中没有重写基类的虚函数,此时子类与基类共用同一张虚表
C:虚表是在运行期间动态生成的
D:一个类的不同对象共享该类的虚表
答案:D
- 假设A类中有虚函数,B继承自A,B重写A中的虚函数,也没有定义任何虚函数,则( )
A:A类对象的前4个字节存储虚表地址,B类对象前4个字节不是虚表地址
B:A类对象和B类对象前4个字节存储的都是虚基表的地址
C:A类对象和B类对象前4个字节存储的虚表地址相同
D:A类和B类虚表中虚函数个数相同,但A类和B类使用的不是同一张虚表
答案:D
2. 问答题
2.1 什么是多态?
那这个问题其实在前面的文章里都有详细的讲解,这里就不展开说了,大家参考之前的文章。
2.2 什么是重载、重写(覆盖)、重定义(隐藏)?
参考之前的文章。
2.3 多态的实现原理?
参考之前的文章。
2.4 inline函数可以是虚函数吗?
这个问题之前没讲,我们来说一说。
内联函数可以是虚函数吗?大家想一想
我们先来回顾一下,什么是内联函数?
以inline修饰的函数叫做内联函数,编译时C++编译器会在调用内联函数的地方展开,用函数体替换函数的调用,没有函数调用建立栈帧的开销,内联函数提升程序运行的效率。
那这样的话,如果一个内联函数真的被处理成内联函数的话,它是没有地址的,那没有地址的函数能是虚函数吗?
肯定是不行的,因为虚函数必须有地址,而且地址要放进虚函数表里面。
那这样来看,内联函数好像不能是虚函数。
但是:
内联函数一定会被当成内联处理吗?
是不是不一定啊。
因为内联说明只是向编译器发出的一个请求,编译器可以选择忽略这个请求。
那我们可以实验一下:
是不是可以啊。
所以:
语法上可以,但是编译器就忽略inline这个属性,这个函数本质就不再是inline,因为虚函数要产生地址放到虚表中去。
2.5 静态成员可以是虚函数吗?
我们可以先试一下:
这里编译器就直接报错,说static和virtual不能一起使用
所以:
静态成员不能是虚函数,因为因为静态成员函数没有this指针,使用类型
::
成员函数就可以调用,但这种调用方式无法访问虚函数表,因为访问虚函数表都是多态的情况下通过对象调用虚函数的方式访问的,静态成员函数的地址不会放进虚函数表。
static和virtual不能一起使用。
2.6 构造函数可以是虚函数吗?
答:
不能,因为对象中的虚函数表指针是在构造函数初始化列表阶段才初始化的。
2.7 析构函数可以是虚函数吗?什么场景下析构函数要搞成虚函数?
答:
析构函数是可以搞成虚函数的,并且有些场景下是不是还需要搞成虚函数重写啊,这个是我们讲的虚函数重写的两个例外之一,大家忘了可以回看之前的文章。
2.8 对象调普通函数快还是虚函数更快?
哪个快呢?
我们可能会觉得调普通函数快,因为调普通函数不需要像调虚函数那样还得通过虚指针去虚函数表里面找。
但是呢,这样说不准确,我问大家,调用虚函数一定要去虚表里面找吗?
在当前这个情况下,其实它们一样快
因为你要比较这个速度的话,要去看情况:
首先如果是普通对象去调用,是一样快的。(普通对象调用不可能构成多态,和普通函数一样去调用)
如果是指针或引用去调用,则调用的普通函数比虚函数快,因为构成多态(即使不满足其它多态的条件,只要是指针或引用调用,他这里统一处理),运行时调用虚函数需要到虚函数表中去查找。
2.9 虚函数表是在什么阶段生成的,存在哪的?
这个在上一篇文章也详细介绍过了。
2.10 C++菱形继承的问题?虚继承的原理?
2.11 什么是抽象类?抽象类的作用?
后面这几个问题前面的文章也都讲了,这里就不提了。