您的位置:首页 > 编程语言 > C语言/C++

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

2017-07-18 21:02 190 查看
条款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;
4000

}


我们可以看到,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.如果类的设计目的是作为基类使用,则也应该声明为虚析构函数
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: