C++中的virtual析构函数创建时机(7)---《Effective C++》

条款7:为多态基类声明virtual析构函数

学习了上篇博客中所讲的virtual关键字之后,我们可以发现virtual关键字对于实现C++的多态至关重要,那么有一个新的问题,我们可以发现有时候我们为一个类声明虚析构函数,有的时候则并没有声明虚析构函数,那么什么时候我们声明,什么时候并不声明虚析构函数呢?正如如下代码所表现的那样:

在这个函数中我们并没有将基类的析构函数声明为virtual函数,那么到底是对的还是错的呢?

#include <iostream>
#include <cstring>
#include <string>
using namespace std;
class A{
public:
    A(int ii, int jj){
        i = ii;
        j = jj;
    }
    virtual void show(){
        cout <<"我是A中的show():"<< i << " " <<j<< endl;
    }
    ~A(){

    }
private:
    int i, j;
};
class B :public A{
public:
    B();
    B(int i, int j, int z) :A(i, j), z(z){
    }
    void show(){
        cout << "我是B中的show():";
        A::show();
        cout << z << endl;
    }
private:
    int z;
};
int main(){
    A* b = new B(1, 2, 3);
    b->show();
    delete b;
    return 0;
}

我们可以看到,b是一种A类型的指针,指向A的派生类B的一个对象,这时B中的z其实并没有被销毁,进而引发内存泄露、资源浪费等一系列严重的问题,那么如何解决这个问题呢?答案就是将基类A的析构函数声明为虚析构函数,即

存在多态(基类函数中至少含有一个virtual)的类系统中(即类的继承中)中我们需要将基类的析构函数声明为virtual;

那么是不是什么情况下我们都应该将函数的析构函数声明为析构函数呢?答案并不是这样。如果一个类不含virtual函数,令其析构函数为虚函数往往是个坏主意,因为析构函数的存储特点,使得代码无法移植,因此,无端将所有类的析构函数声明为virtual,就像从未将其声明为virtual一样,都是错误的。

这里有一些特例,需要掌握的,暂且当做补充吧!例如标准库中的string和STL容器,都没有虚析构函数,如果我们让某个类继承上述这种类,然后通过指针访问,删除指针的时候也将引发错误,如:

class stringSelf:public string{
    ...
};
stringSelf * ss=new StringSelf("hello");
string *ps;
ps=ss;
delete ps;//*ps的资源被泄露,因为stringSelf的析构函数没有被调用

总结如下:

1.在基类中如果存在1个或者以上的虚函数,那么我们就需要将其析构函数声明为虚析构函数,因为如果不将其声明为析构函数,则会出现“局部销毁”,进而引发内存泄露等一系列问题;

2.如果类的设计目的是作为基类使用,则也应该声明为虚析构函数

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值