虚函数是C++实现多态的一个手段.但是当进行Upcasting的时候,会不会出现内存泄露了?今天我们就来解开它的面纱.

Code

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
#include <iostream>
using namespace std;
class Base{
public:
Base(){cout<<"In Base()"<<endl;}
~Base(){cout<<"In ~Base()"<<endl;}
virtual void DoSomething(){cout<<"Do something in class Base"<<endl;}
};
class Derived:public Base{
public:
Derived(){cout<<"In Derived()"<<endl;}
~Derived(){cout<<"In ~Derived"<<endl;}
void DoSomething(){cout<<"Do something in class Derived"<<endl;}
};
int main(){
Base *pTest = new Derived();
pTest->DoSomething();
delete pTest;
return 0;
}

Error

1
no error

输出结果:

1
2
3
4
In Base()
In Derived()
Do something in class Derived
In ~Base()

一眼就发现子类没有被析构,果然有内存泄露.

Analysis

我们知道,子类指针在被delete时会调用子类析构,父类析构.这儿是由于

1
Base *pTest = new Derived();

这行代码把子类指针upcasting成父类指针.此时,pTest指针只有拥有子类继承于父类的内容.
那么为什么会执行子类的DoSomething函数?一切都归结于virtual关键字,它是多态产生的原因.
那么,我们只要调用子类的析构函数,这样子类和父类不是都可以被析构了吗.因此,只要在父类的析构函数加上virtual,内存泄露的问题就解决了.

1
virtual ~Base(){cout<<"In ~Base()"<<endl;}

这样我们有如下的输出

1
2
3
4
5
In Base()
In Derived()
Do something in class Derived
In ~Derived
In ~Base()

Summary

第一,要知道Upcasting的原理
第二,那就是用virtual实现多态.