c++复习基础要点03 虚析构函数、虚函数表
1.虚析构函数的作用:
当基类对象指针通过new动态创建一个子类的对象时,通过该指针释放子类对象时,如果基类的析构函数不是虚函数,则释放该对象时只会调用基类的析构函数而不会调用子类析构函数。这样子类释放对象时就无法释放已分配的资源。
如果基类的析构函数为虚函数,则在基类对象指针去释放子类对象时,就会先调用子类的析构函数,在调用基类的析构函数:
#include<iostream>
using namespace std;
class A
{
public:
virtual void fun()
{
cout<<"thisis virtual for A"<<endl;
}
virtual~A()
{
cout<<"thisis virtual ~ for A"<<endl;
}
};
class B:public A
{
public:
voidfun()
{
cout<<"thisis virtual for B"<<endl;
}
virtual~B()
{
cout<<"thisis virtual ~ for B"<<endl;
}
};
int main()
{
A*a;
a=newB;
a->fun();
deletea;
return0;
}
结果:
this is virtual for B
this is virtual ~ for B
this is virtual ~ for A
当virtual ~A() 去掉virtual时,结果为:
this is virtual for B
this is virtual ~ for A
也就是说,类B的析构函数根本就没被调用,一般情况下类的析构函数里面都是释放内存资源,而析构函数不被调用的话就会造成内存泄漏。
所以基类的析构函数应该被定义为虚函数,这样做是为了当用一个基类的指针删除一个派生类的对象时,派生类的析构函数会被调用。
当然,并不是要把所有类的析构函数都写成虚函数。因为当类里面有虚函数的时候,编译器会给类添加一个虚函数表,里面来存放虚函数指针,这样就会增加类的存储空间。所以,只有当一个类被用来作为基类的时候,才把析构函数写成虚函数。
2.虚函数表
多态性可分为两类:静态多态和动态多态。函数重载和运算符重载实现的多态属于静态多态,动态多态性是通过虚函数实现的。
每个含有虚函数的类有一张虚函数表(vtbl),表中每一项是一个虚函数的地址, 也就是说,虚函数表的每一项是一个虚函数的指针。
没有虚函数的C++类,是不会有虚函数表的
例子:
class Class1
{
public:
m_data1;
m_data2;
virtual vfunc1();
virtual vfunc2();
virtual vfunc3();
};
图示:
class Class2 : public Class1
{
public:
m_data3;
virtual vfunc2();
};
图示:
虚函数表的指针4个字节大小(vptr),存在于对象实例中最前面的位置(这是为了保证取到虚函数表的有最高的性能——如果有多层继承或是多重继承的情况下)。这意味着我们通过对象实例的地址得到这张虚函数表,然后就可以遍历其中函数指针,并调用相应的函数。
补充:软件开发 , C++ ,