C++基础---虚析构函数与纯虚析构函数

来源:互联网 发布:新广行风热线网络直播 编辑:程序博客网 时间:2024/06/06 23:55

1. 虚析构函数与纯虚析构函数

1.1 虚析构函数与纯虚析构函数的定义

  • 虚析构函数:为了解决基类的指针指向派生类对象,并用基类的指针删除派生类对象
  • 虚析构函数:当且仅当类里包含至少一个虚函数的时候才去声明虚析构函数,无故的声明虚析构函数和永远不去声明一样是错误的;

    class <类名>{virtual ~<类名>();…};即:virtual ~A();
  • 纯虚析构函数:抽象类是准备被用做基类的,基类必须要有一个虚析构函数,纯虚函数会产生抽象类,所以方法很简单,在想要成为抽象类的类里声明一个纯虚析构函数;

    class <类名>{virtual ~<类名>() = 0;…};即:virtual ~A() = 0;

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

1.2 带有虚函数功能的类需要一个虚析构函数的原因

  • 如果一个类有虚函数功能,它经常作为一个基类使用;
  • 如果它是一个基类,它的派生类经常使用new来分配;
  • 如果一个派生类对象使用new来分配,并且通过一个指向它的基类的指针来控制,那么它经常通过一个指向它的基类的指针来删除它;
    注:
    (1)如果基类没有虚析构函数,结果将是不确定的,实际发生时,派生类的析构函数永远不会被调用。
    (2)如果基类有虚析构函数的话,最底层的派生类的析构函数最先被调用,然后各个基类的析构函数被调用。

1.3 虚析构函数的注意点

  • 由于析构函数不允许有参数,因此它不可能实现重载,那么一个类就只能有一个虚析构函数;
  • 只要基类的析构函数被声明为虚函数,则派生类的析构函数无论说明与否,都自然是析构函数;
  • 如果基类中定义了虚函数,析构函数也应说明为虚函数,这样对内存的回收更准确些;
    注:在C++中虚构造函数是不存在的,因此也无法声明。

1.4 虚析构函数的实例

  • (1)在带有虚函数的基类中定义普通析构函数

    #include <iostream>using namespace std;class A{public:    A(){cout<<"A()..."<<endl;}    ~A(){cout<<"~A()..."<<endl;}public:    virtual void func1()    {        cout<<"A::func1()"<<endl;    }};class B : public A{public:    B(){cout<<"B()..."<<endl;}    ~B(){cout<<"~B()..."<<endl;}public:    virtual void func1()    {        cout<<"B::func1()"<<endl;    }};int main(){    A *pb = new B;    pb->func1();    delete pb;    system("pause");    return 0;}=>A()...  B()...  B::func1()  ~A()...注:派生类继承自基类,那么基类就只会存在于派生类中,直到派生类调用析构函数后。当上述这种情况,基类的析构函数调用比派生类要早,会造成的一种情况就是类成员不存在了,而类本身却还在,但是类存在的情况下,类成员应该还存在。所以这就矛盾了,应该派生类的析构函数会先被调用,基类的析构函数再被调用。
  • (2)在带有虚函数的基类中定义虚析构函数

    #include <iostream>using namespace std;class A{public:    A(){cout<<"A()..."<<endl;}    virtual ~A(){cout<<"virtual ~A()..."<<endl;}public:    virtual void func1()    {        cout<<"A::func1()"<<endl;    }};class B : public A{public:    B(){cout<<"B()..."<<endl;}    virtual ~B(){cout<<"virtual ~B()..."<<endl;}public:    virtual void func1()    {        cout<<"B::func1()"<<endl;    }};int main(){    A *pb = new B;    pb->func1();    delete pb;    system("pause");    return 0;}=>A()...  B()...  B::func1()  virtual ~B()...  virtual ~A()...

    注:析构函数的作用并不是删除对象,而是撤销对象占用内存之前完成的一些清理工作。
    (1)抽象类是准备被用做基类的,基类必须要有一个虚析构函数,纯虚函数会产生抽象类,所以在想要成为抽象类的类里声明一个纯虚析构函数。
    (2)定义一个函数为虚函数,不代表该函数未被实现,只是为了来实现多态。
    (3)定义一个函数为纯虚函数,才表示函数未被实现 ,定义它是为了实现一个接口,起一个规范作用。继承抽象类的派生类要实现这个函数。


参考文献:
[1]《C++全方位学习》范磊——第十三章
[2]《C++程序设计教程(第二版)》钱能——第五章、第六章、第七章
[3]《C++ Primer(第5版)》王刚 杨巨峰——第一章、第六章
[4] 百度搜索关键字:C++函数、虚析构函数、纯虚析构函数

0 0
原创粉丝点击