一、构造函数不能声明为虚函数

为什么构造函数不能声明为虚函数呢?


1、构造一个对象的时候,必须知道对象的实际类型,而虚函数是在运行期间确定实际类型的。如果构造函数为虚函数,则在构造一个对象时,由于对象还未构造成功,编译器还无法知道对象的实际类型,是该类本身还是派生类。无法确定。


2、虚函数的执行依赖于虚函数表,而虚函数表是在构造函数中初始化的,即初始化vptr,让它指向虚函数表。如果构造函数为虚函数,则在构造对象期间,虚函数表还没有被初始化,将无法进行。


二、析构函数可以声明为虚函数,而且有时是必须声明为虚函数。

虚析构函数是为了解决这样的一个问题:基类的指针指向派生类对象,并用基类的指针删除派生类对象时,要使用虚析构函数。


如果某个类不包含虚函数,那一般是表示它将不作为一个基类来使用。当一个类不准备作为基类使用时,使析构函数为虚一般是个坏主意。因为它会为类增加一个虚函数表,使得对象的体积翻倍,还有可能降低其可移植性。


所以基本的一条是:无故的声明虚析构函数和永远不去声明一样是错误的。实际上,很多人这样总结:当且仅当类里包含至少一个虚函数的时候才去声明虚析构函数。


抽象类是准备被用做基类的,基类必须要有一个虚析构函数,纯虚函数会产生抽象类,所以方法很简单:在想要成为抽象类的类里声明一个纯虚析构函数。


只有当一个类被用来作为基类的时候,才把析构函数写成虚函数。


所以注意如果基类不是虚析构函数的话可能会有以下两点问题:


1、子类所分配的内存不能被释放

2、子类中成员变量类所分配的内存也不能被释放,因为子类析构函数没有被调用,其变量的析构函数肯定也没被调用了。


总之:


基类指针可以指向派生类的对象(多态性),如果删除该指针delete []p;就会调用该指针指向的派生类析构函数,而派生类的析构函数又自动调用基类的析构函数,这样整个派生类的对象完全被释放。如果析构函数不被声明成虚函数,则编译器实施静态绑定,在删除基类指针时,只会调用基类的析构函数而不调用派生类析构函数,这样就会造成派生类对象析构不完全。所以,将析构函数声明为虚函数是十分必要的。

​https://baijiahao.baidu.com/s?id=1721484839313440041&wfr=spider&for=pc​


虚函数表存放在全局数据区