多态的总结
什么是多态?
答:多态是多种形态,是为了完成某种行为时,不同对象会产生不同的形态(结合车票例子解释)
2. 什么是重载、重写(覆盖)、重定义(隐藏)?
答:重载的条件是:在同一作用域下,同名函数的(参数个数,参数类型,参数顺序不同)构成重载。
而重写的条件是:在不同作用域下,(函数名,返回类型,参数列表)均相同,并且是虚函数构成的,叫做重写
最后,重定义只要求不同作用域下,函数名相同的函数叫做重定义。两个基类与派生类的同名函数,不是重写就是重定义
3. 多态的实现原理?
答:多态分为静态多态(编译期间)和动态多态(运行期间)
而静态多态:传不同参数。调用不同函数。自动识别类型,根据函数名修饰规则(比如像函数重载,编译时进行匹配,过了之后,如果走到链接的时候,通过函数名修饰规则去找)去寻找对应的变量
而动态多态:传不同对象,调不同函数。(继承中虚函数重写+父类指针调用)就通过生成虚函数表,做到指向哪个类,就去哪个类的对象的虚函数表找。即指向谁就调用谁
4. inline函数可以是虚函数吗?
答:可以,不过编译器就忽略inline属性,这个函数就不再是inline,因为虚函数要放到虚表中去。
5. 静态成员可以是虚函数吗?
答:不能,因为静态成员函数没有this指针,使用类型::成员函数的调用方式无法访问虚函数表,所以静态成员函数无法放进虚函数表。
6. 构造函数可以是虚函数吗?
答:不能,因为对象中的虚函数表指针是在构造函数初始化列表阶段才初始化的。
形象地说就是:先有鸡还是先有蛋?调构造函数,如果是虚函数,虚函数的目的就是实现多态,那么实现要多态,你连虚表都没有,你去哪里找虚函数地址?因此对象初始化好了才有虚表,通过虚表找虚函数。
7. 析构函数可以是虚函数吗?什么场景下析构函数是虚函数?
答:可以,并且最好把基类的析构函数定义成虚函数。基类只要定义了虚函数,那么派生类的析构函数都会与基类的析构函数构成重写,其中它的内部原理是统一变成一个叫destructor的函数名。来保证对象的正确销毁,做到先释放派生类,再去释放基类的顺序。
8. 对象访问普通函数快还是虚函数更快?
答:首先得分情况:如果是普通对象,是一样快的。如果是指针对象或者是引用对象,则调用的普通函数快,因为构成多态,运行时调用虚函数需要到虚函数表中去查找。
9. 虚函数表是在什么阶段生成的,存在哪的?
答:虚函数表是在编译阶段就生成的,一般情况下存在代码段(常量区)的。(+多态那篇文章里的证明)
10. C++菱形继承的问题?虚继承的原理?
答:C++的菱形继承会存在二义性和冗余性。
而虚继承就是为了解决上面的问题的:通过一个虚基表,虚基表存的是基类偏移量的表,通过虚基表计算变量在对象里面的地址,再随着地址去访问
11. 什么是抽象类?抽象类的作用?
答:抽象类就是在虚函数后面写=0;抽象类强制重写了虚函数,另外抽象类体现出了接口继承关系。
最后到了本次鸡汤:
![]()