问题一:哪些函数不能实现成虚函数
虚函数依赖:
1:虚函数能产生地址,存储在vftable中
2:对象必须存储在 vfptr-> vftable-> 虚函数地址
**构造函数 **
1:virtual + 构造函数 (NO,不可以在构造函数前加virtual
2:构造函数中 调用的任何函数,都是静态绑定(lg:派生类对象构造过程中,先调用基类的构造函数,由于要通过对象拿到内存中的虚函数表指针,此时基类对象还没有构造出来,如何实现动态绑定?)
**static静态成员方法,也不可以加virtual,static静态成员方法的调用不基于对象 **
析构函数 可以 加 virtual,析构函数调用的时候,对象是存在的,所以可以通过对象内存拿到vfptr,进而找到vftable ,最后找到虚函数地址
问题二:虚析构函数,析构函数的调用的时候,对象是存在的
什么时候把基类的析构函数必须实现成虚函数?当 用基类的指针(引用)指向堆上new出来的派生类对象的时候
delete pb(pb是基类指针); 他调用析构函数的时候,必须发生动态绑定,否则会导致派生的析构函数无法调用,会有内存泄漏风险.
代码1
class Base{public:Base(int data=10):ma(data){ cout<<"Base()"<<endl; }//虚函数virtual void show(){cout<<"Base Show()"<<endl;}//虚函数virtual void show(int){cout<<"Base Show(int)"<<endl;}~Base(){cout<<"~Base()"<<endl;}protected:int ma;};class Derive : public Base{public:Derive(int data=20):Base(data),mb(data){ cout<<"Derive()"<<endl; }void show(){cout<<"Derive Show()"<<endl;} ~Derive(){cout<<"~Derive()"<show(); return 0; //这个mian函数执行完成后执行顺序 //Base()构造函数->Derive()构造函数->~Derive()析构->~Base()析构 ,注意和下面的mian函数对比}int main1(){ Base *pb=new Derive d(20); pb->show(); delete pb; //这个main函数执行完成后执行顺序 //Base()构造函数->Derive()构造函数->~Base()析构 //发现 Derive的析构函数没有被调用,如果Derive中使用了外部资源,会有内存泄漏 ,注意和上面的mian函数对比 //pb是Base类型,所以去Base中看析构函数,发现是普通函数,所以执行编译期绑定,直接调用了Base的析构方法 //所以要将Base中的析构函数加上Virtual,当基类的析构方法是虚函数时,那么派生类的析构函数自动成为虚函数,发生动态绑定 //这是调用的是Derive的析构函数,在执行完Derive的析构函数后还会负责将基类的析构函数调用完成. return 0;}