发布时间:2022-11-28 文章分类:编程知识 投稿人:赵颖 字号: 默认 | | 超大 打印

问题一:哪些函数不能实现成虚函数
虚函数依赖:
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()"<<endl;}
	private:
        int mb;
};
int main0(){
	 Derive d(20);
         Base *pb=&d;
	 pb->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;
}