继承和多态常见的面试问题

  1. 什么是多态?

简单来说,多态是不同对象同种行为产生不同状态

即在不同继承关系的类对象,去调用同一函数,产生了不同的行为

  1. 什么是重载、重写(覆盖)、重定义(隐藏)?
  1. 重载:在同一作用域中,函数名相同和参数不同构成重载

  2. 重写:在基类和继承类域中,对于虚函数,函数名,参数和返回值相同(特例除外),构成重写

  3. 重定义:在基类和继承类域中,函数名相同,不构成重载就构成重定义

  1. 多态的实现原理?
  1. 对于虚函数类会在对象的成员变量中生成虚函数表指针,指向的虚函数表中储 了该对象的虚函数地址

  2. 对于派生类会继承基类的虚函数表,如果派生类重写了虚函数,则会对继承的虚函数表中对应的函数地址进行覆盖成派生类对象的虚函数

  3. 当对象调用虚函数时会先找到虚函数表,通过虚函数表找到对应的虚函数,由此构成多态

  1. inline函数可以是虚函数吗?

可以,不过编译器会忽略inline属性,这个函数就不再是inline,因为虚函数要放到虚表中去

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

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

  1. 构造函数可以是虚函数吗?

不能,因为对象中的虚函数表指针是在构造函数初始化列表阶段才初始化的,如果构造函数为虚函数,会先在对象中的虚函数查找对应虚函数,而此时虚函数表没有生成(动态多态是运行时绑定)

  1. 析构函数可以是虚函数吗?什么场景下析构函数是虚函数?
  1. 可以,并且最好把基类的析构函数定义成虚函数

  2. 当基类指针指向new出来的基类对象或new出来的派生类对象时,需要使用指针进行释放对象,此时需要析构函数为虚函数,保证指针指向的对象成功释放

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

如果是普通对象,是一样快的

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

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

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

  1. C++菱形继承的问题?虚继承的原理?
  1. 菱形继承存在数据冗余和二义性的问题

  2. 虚继承会让继承的父类在成员变量中生成虚基表指针,指向虚基表会储存其继承的基类成员变量距离其成员变量的距离,通过该距离找到其基类成员变量,而两个继承的父类中的虚基表指向同一份父类的父类成员变量

注意:不要把虚函数表和虚基表搞混了

  1. 什么是抽象类?抽象类的作用?
  1. 抽象类用来表示现实中一些抽象的事物类型,抽象类不具有实例,派生类只是继承其虚函数接口,它强制派生类重写虚函数,否则派生类也是抽象函数

  2. 抽象类体现出了接口继承关系 ,以及用来更好的表示现实中一些抽象的事物类型