[C++]虚析构函数的做用

 
C++中的虚析构函数到底何时有用的,什么做用呢。
 
一.虚析构函数的做用
总的来讲虚析构函数是为了不内存泄露,并且是当子类中会有指针成员变量时才会使用获得的。也就说 虚析构函数使得在删除指向子类对象的基类指针时能够调用子类的析构函数达到释放子类中堆内存的目的,而防止内存泄露的
咱们知道,用C++开发的时候,用来作基类的类的析构函数通常都是虚函数。但是,为何要这样作呢?下面用一个小例子来讲明:
 1 #include<iostream>
 2 using namespace std;
 3 
 4 class ClxBase
 5 {
 6     public:
 7         ClxBase() {};
 8         virtual ~ClxBase() { cout<<"delete ClxBase"<<endl; };
 9 
10         virtual void DoSomething() { cout << "Do something in class ClxBase!" << endl;  };
11 
12 };
13 
14 class ClxDerived : public ClxBase
15 {
16     public:
17         ClxDerived() {};
18         ~ClxDerived() { cout << "Output from the destructor of class ClxDerived!" << endl;  };
19 
20         void DoSomething() { cout << "Do something in class ClxDerived!" << endl;  };
21 
22 };
23 
24 int main(int argc, char const* argv[])
25 {
26      ClxBase *pTest = new ClxDerived;
27      pTest->DoSomething();
28      delete pTest;
29     return 0;
30 }

可是,若是把类ClxBase析构函数前的virtual去掉,那输出结果就是下面的样子了: ios

没有调动子类的析构函数
也就是说,类ClxDerived的析构函数根本没有被调用!通常状况下类的析构函数里面都是释放内存资源,而析构函数不被调用的话就会形成内存泄漏。我想全部的C++程序员都知道这样的危险性。固然,若是在析构函数中作了其余工做的话,那你的全部努力也都是白费力气。
因此,文章开头的那个问题的答案就是--这样作是为了当用一个基类的指针删除一个派生类的对象时,派生类的析构函数会被调用。
固然,并非要把全部类的析构函数都写成虚函数。由于当类里面有虚函数的时候,编译器会给类添加一个虚函数表,里面来存放虚函数指针,这样就会增长类的存储空间。因此,只有当一个类被用来做为基类的时候,才把析构函数写成虚函数。程序员

总结一下虚析构函数的做用:
(1)若是父类的析构函数不加virtual关键字
当父类的析构函数不声明成虚析构函数的时候,当子类继承父类,父类的指针指向子类时,delete掉父类的指针,只调动父类的析构函数,而不调动子类的析构函数。
(2)若是父类的析构函数加virtual关键字
当父类的析构函数声明成虚析构函数的时候,当子类继承父类,父类的指针指向子类时,delete掉父类的指针,先调动子类的析构函数,再调动父类的析构函数。 函数

二.虚析构函数的原理分析spa

 

 1 #include<iostream>
 2 using namespace std;
 3 
 4 class Base
 5 {
 6 public:
 7     Base(){cout<<"create Base"<<endl;}
 8     virtual ~Base(){cout<<"delete Base"<<endl;}
 9 };
10 
11 class Der : public Base
12 {
13 public:
14     Der(){cout<<"create Der"<<endl;}
15     ~Der(){cout<<"Delete Der"<<endl;}
16 };
17 int main(int argc, char const* argv[])
18 {
19     Base *b = new Der;
20     delete b;
21 
22     return 0;
23 }

 

从建立讲起,用gdb调试你会发现, 
(1)先调用父类的构造函数,再调用子类的构造函数.net

这里有一个问题:父类的构造函数/析构函数与子类的构造函数/析构函数会造成多态,可是当父类的构造函数/析构函数即便被声明virtual,子类的构造/析构方法仍没法覆盖父类的构造方法和析构方法。这是因为父类的构造函数和析构函数是子类没法继承的,也就是说每个类都有本身独有的构造函数和析构函数。指针

(2)而因为父类的析构函数为虚函数,因此子类会在全部属性的前面造成虚表,而虚表内部存储的就是父类的虚函数调试

 

(3)当delete父类的指针时,因为子类的析构函数与父类的析构函数构成多态,因此得先调动子类的析构函数;之因此再调动父类的析构函数,是由于delete的机制所引发的,delete 父类指针所指的空间,要调用父类的析构函数。 
因此结果就是这样 
这里写图片描述code

相关文章
相关标签/搜索