C++中继承与多态的微冷面试题你了解多少?

  • 什么是菱形继承?菱形继承的问题是什么?

简单的说,就是B继承A,C也继承了A,然后D又继承了B和C,所以造成继承关系相当于一个菱形,具体可以看这篇文章,讲的非常详细。
关于菱形继承还有虚基表的介绍
菱形继承的问题就是会造成代码冗余,对于D对象而言,同时包含了C对象中的A对象,又包含了B对象中的A对象,所以会造成数据二义性以及代码冗余。

  • 什么是菱形虚拟继承?如何解决数据冗余和二义性的

菱形虚拟继承就是将中间继承关系改为虚拟继承(也就是将B继承A以及C继承A的继承关系改为virtual继承关系),这样对于B对象以及C对象而言,他们只会存在一份A对象,这份A对象就是通过B对象以及C对象中存储的虚基表指针进行定位,指向A对象。虽然这样会造成内存使用增大,但是这样避免了数据二义以及代码冗余(详细说明,可以参考上边那篇文章)。

  • 继承和组合的区别?什么时候用继承?什么时候用组合

继承通常被称为白箱复用,因为在继承方式中,父类的内部细节对子类是可见的,所以也使得封装性被破坏。(子类中的实现与它的父类有如此紧密的依赖关系,以至于父类实现中的任何变化必然会导致子类发生变化。当你需要复用子类时,实现上的依赖性就会产生一些问题。如果继承下来的实现不适合解决新的问题,则父类必须重写或被其他更适合的类替换(解决方案:只继承抽象类))。
组合通常被称为黑箱复用,因为对象的内部细节是不可见的,并且组成存在较少的依赖型,不会破坏封装性(对象的实现基于接口,对象也只能通过接口访问)
二者关系为“是”,并且接口公开,则用继承。
二者关系为“有”,首选择组合

详细说明参考以下两篇文章
优先使用对象组合
继承和组合的概念

  • 什么是多态?

多态就是在不同继承关系的类对象中,去调用同一函数,产生了不同的行为。

  • 什么是重载、重写(覆盖)、重定义(隐藏)?

重载:同一个作用域,多个函数函数名相同、参数不同,这些函数构成重载。
重写:基类和派生类中出现函数名、参数、返回值相同(协变除外)的两个虚函数,则这两个虚函数构成重写。
重定义:基类和派生类出现函数名相同的两个函数,,如果不是重写,则这两个函数构成重定义。

  • 多态的实现原理?

满足多态的两个条件就是虚函数覆盖和对象的指针或者引用调用虚函数,满足多态以后的函数调用,不是在编译时确定的,是运行起来以后到
对象的中去找的。不满足多态的函数调用时编译时就确认好了。

  • inline函数可以是虚函数吗?

不能,因为inline函数没有地址,无法把地址放到虚函数表中

  • 静态成员可以是虚函数吗?

不能,因为静态成员函数没有this指针,使用类型::成员函数的调用方式 无法访问虚函数表,所以静态成员函数无法放进虚函数表。

  • 构造函数可以是虚函数吗?

不能,因为对象中的虚函数表指针是在构造函数初始化列表阶段才初始
化的。

  • 析构函数可以是虚函数吗?什么场景下析构函数是虚函数?

可以,并且最好把基类的析构函数定义成虚函数。
当出现继承关系时,将析构函数写为虚函数,避免内存泄漏(使用切片的方式申请资源,最终若析构函数不是虚函数,不构成多态,则会造成内存泄漏)

  • 对象访问普通函数快还是虚函数更快?

首先如果是普通对象,是一样快的。如果是指针对象或者是引用对象,则调用的普通函数快,因为构成多态,运行时调用虚函数需要到虚函数表中去查找。

  • 虚函数表是在什么阶段生成的,存在哪的?

虚函数表是在编译阶段就生成的,一般情况下存在代码段(常量区)的。

  • 什么是抽象类?抽象类的作用?

在虚函数的后面写上 =0 ,则这个函数为纯虚函数。包含纯虚函数的类叫做抽象类(也叫接口类),抽象类不能实例化出对象。派生类继承后也不能实例化出对象,只有重写纯虚函数,派生类才能实例化出对象。
作用:抽象类中纯虚函数规范了派生类必须重写,另外纯虚函数更体现出了接口继承,这个也叫作接口继承,也就是派生类继承的是基类的接口,基类需要重写,达成多态。

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值