现在的位置: 首页 > 综合 > 正文

c++复习基础要点03 虚析构函数、虚函数表

2018年02月21日 ⁄ 综合 ⁄ 共 1457字 ⁄ 字号 评论关闭

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),存在于对象实例中最前面的位置(这是为了保证取到虚函数表的有最高的性能——如果有多层继承或是多重继承的情况下)。这意味着我们通过对象实例的地址得到这张虚函数表,然后就可以遍历其中函数指针,并调用相应的函数。

 

 

抱歉!评论已关闭.