问题一:哪些函数不能实现为虚函数
注:虚函数的条件:
虚函数能产生地址,存在vftable中
对象必须存在(vfptr->vftable->虚函数地址)
- 构造函数
- virtual+构造函数,错误
- 构造函数中调用虚函数,不会发生动态绑定(只发生静态绑定)
static
静态成员方法也不能加virtual
为什么需要虚析构
首先看如下例子:
#include <iostream>
#include <typeinfo>
using namespace std;class Base
{
public:Base(int data) :ma(data) {cout << "Base()" << endl;}~Base(){cout << "~Base()" << endl;}virtual void show() { cout << "Base::show()" << endl; }//virtual void show(int) { cout << "Base::show(int)" << endl; }protected:int ma;
};class Derive : public Base
{
public:Derive(int data = 20) : Base(data), mb(data) ,ptr(new int(data)){cout << "Derive()" << endl;}~Derive(){delete ptr;cout << "~Derive()" << endl;}void show() { cout << "Derive::show()" << endl; }
private:int mb;int *ptr;
};int main()
{Base* pb = new Derive(10);pb->show(); // 动态绑定delete pb;return 0;
}
输出结果为:
Base()
Derive()
Derive::show()
~Base()
可以发现没有调用派生类的析构函数 ~Derive(),这将会导致内存泄漏.
这是因为析构函数不是虚函数,delete pb
时是静态绑定只调用基类的析构,而不回去调用派生类的析构。
解决方法
将基类析构设置为virtual
,此时派生类vftable
的虚函数就有&Derive::show()
和&Derive::~Derive()
.这样delete pb
时会发生动态绑定调用派生类析构,然后根据继承机制再调用基类析构。
要点
- 虚析构函数,析构函数调用时,对象是存在的
- 基类的析构函数是
virtual
虚函数,则派生类的析构函数自动成为虚函数,虽然这两个析构不同名 - 什么时候基类的析构必须实现为虚函数?
答:基类指针(引用)指向堆上new
出来的派生类对象时, delete 基类指针,调用析构时必须发生动态绑定,否则导致派生类析构不会被调用,造成内存泄漏