1.什么是多态,C++的多态如何实现
多态就是同一函数名的不同形态,提供具有不同行为的接口, C++的多态又分为静态多态和动态多态。 静态多态(编译时多态)通过重载和模板实现, 动态(运行时)多态通过虚函数和继承实现。
2. 虚函数的实现机制是什么
虚函数是通过虚函数表来实现的,虚函数表中存放着一个类中所有的虚函数地址。在类对象中的内存空间头部存放着一个虚函数指针 这个指针指向虚函数表,当子类对象对父类的虚函数进行重写时,虚函数表中的此函数的地址就会改变,在运行时指明实际调用的函数。
2.1虚函数时在运行时确定还是在编译时确定的,如何确定的
在运行时确定,通过虚函数表来指明实际调用哪个函数
2.2 虚函数存在类中还是存在类对象中(是否存共享虚函数表)
存在类中,不同的类的对象共享一张虚函数表。
2.3 构造函数和析构函数中调用虚函数会怎么样(我们犯了一个盲区,这个问题是说在其中调用虚函数)
从语法上来说没问题,但是调用不能实现效果,在调用构造函数的时候,首先调用父类的构造函数,此时下调到子类的构造函数,而子类此时还没有被初始化,使用这些尚未初始化的数据一定会出错。
在析构函数中实现的时候,先进行子类的析构,当进入父类的析构时,子类的已经被销毁,无法实现多态。
(直接看代码:调用虚函数)
2.4 问题应该是 析构函数能被设置成虚函数吗
可以 当基类指针指向派生类对象时,析构函数只会调用基类的析构函数,从而造成内存泄漏。(原因:在调用普通函数时,在编译期间已经确定了它所要调用的函数(静态绑定),因为p是Person*类型,因此只会调用基类的析构函数。)
将父类析构函数改变成虚函数后,会先调用派生类的析构函数,后调用了基类的析构函数。(原因:当我们把基类析构函数定义为虚函数时,在调用析构函数时,会在程序运行期间根据指向的对象类型到它的虚函数表中找到对应的虚函数(动态绑定),此时找到的是派生类的析构函数,因此调用该析构函数;而调用派生类析构函数之后会再调用基类的析构函数,因此不会导致内存泄漏。)
3. C++中的内存布局(内存模型)
如果有虚函数的话,虚函数表表指针在内存空间的头部,然后按照父类到子类(继承顺