1.如何理解多态。
多态的实现效果:同样的调用语句有多种的表现形态;
多态实现的三个条件:有继承、有virtual重写、有父类指针(引用)指向子类对象;
多态的C++实现:virtual关键字,告诉编译器这个函数要支持多态;不是根据指针类型判断如何调用;
而是根据指针所指向的实际对象类型来判断如何调用
多态的理论基础:动态联编PK静态联编,根据实际的对象类型来判断重写函数的调用。
多态的重要意义:设计模式的基础是框架的基石;
实现多态的理论基础:虚函数表的指针做函数参数;
C函数指针是C++至高无上的荣耀。
多态原理探究: 与面试官展开讨论(见本博的多态原理探究 vptr指针)
2.谈谈C++编译器如何实现多态
C++编译器多态实现原理,vptr指针,虚函数表
3.谈谈你对重写、重载的理解
答:重写是针对两个类的,存在继承关系的,并且函数原型完全相同,使用virtual声明之后能够产生多态,如果不使用vir,那叫重定义,那么子类的函数会对父类同名函数进行重写。
重载是针对同一个类 ,有同名函数,但是形参类型或形参个数或者形参顺序不一样。
子类无法重载父类的函数,父类同名函数将被名称覆盖。
4.是否可将类中的每个成员函数都声明为虚函数,为什么
答:是可以的,但不建议,因为虚函数表是一个寻址的过程,会很浪费时间,并且也浪费内存,vptr指针本身需要占用空间。
5.构造函数中能调用虚函数,实现多态吗?
1)对象中的vptr指针什么时候被初始化?
对象在创建时,由编译器对VPTR指针进行初始化
只有当对象的构造完全结束后VPTR的指向才最终确定
父类对象的VPTR指向父类虚函数表
子类对象的VPTR指向子类虚函数表
答案是不能的,因为只有当对象的构造完全结束后VPTR的指向才最终确定,所以当在父类构造函数里调用virtual声明的print()函数,并没有调用子类的,因为此时vptr指针指向的是父类的虚函数表。这是vptr指针的初始化问题,它是分步初始化的。
~~~当执行父类的构造函数时候,c1.vptr指向父类的虚函数表,当父类的构造函数运行完毕后,会把c1.vptr指向子类的虚函数表。
6.虚函数表指针(vptr)被编译器初始化的过程,你是如何理解的?
C++编译器多态实现原理
7.父类的构造函数中调用虚函数,能发生多态吗?
c++编译器多态实现原理
8.为什么要定义虚析构函数。
在什么情况下应当声明虚函数
构造函数不能是虚函数,建立一个派生类对象时,必须从类层次的根开始,沿着继承路径逐个调用基类的构造函数。只有当对象的构造完全结束后VPTR的指向才最终确定,这个时候,对象都没有构造结束,也就表示vptr指针还没有确定,也就是没有指向的内存空间,那么它怎么找对应的虚函数表呢???
析构函数可以是虚的,虚析构函数用于指针delete 运算符正确析构动态对象。
9. 父类指针和子类指针的步长
1)铁律1:指针也只一种数据类型,C++类对象的指针 p++/p--,仍然可用。
2)指针运算是按照指针所指的类型进行的。
p++ == p=p+1 // p=(unsigned int)basep+sizeof(*p) 步长
3)结论:父类p++与子类p++步长不同;不要混搭,不要在数组上使用多态。