C++中的virtual析构函数

来源:互联网 发布:约看电影的软件 编辑:程序博客网 时间:2024/04/29 10:25

当一个类被继承时,在它的子类析构的过程中会有一个析构链\
调用子类的析构函数\
销毁类对象的数据成员\
调用父类的析构函数\

1.下面看一个在父类的析构函数没有被声明为virtual的时的测试程序以及输出结果。
不保证下面的代码在拷贝后一定能运行!

#include <iostream>using namespace std;class parent{public:    ~parent(){ cout << "~parent" << endl; }};class child : public parent{public:    ~child(){ cout << "~child" << endl; }};void testPointer(){    parent *p = new child();    delete p;}int _tmain(int argc, _TCHAR* argv[]){    cout << "_____________________________________" << endl;    testPointer();    cout << "_____________________________________" << endl;    system("pause");    return 0;}

输出结果:
这里写图片描述
delete时只调用了父类的析构函数,没有电泳调用子类的析构函数。\
这就可能在我们程序运行过程中导致内存泄漏,以及其他根据业务不\
同的错误。

2.当父类的析构函数被virtual修饰时的测试代码如下:

#include <iostream>using namespace std;class parent{public:    virtual ~parent(){ cout << "~parent" << endl; }};class child : public parent{public:    virtual ~child(){ cout << "~child" << endl; }};void testPointer(){    parent *p = new child();    delete p;}int _tmain(int argc, _TCHAR* argv[]){    cout << "_____________________________________" << endl;    testPointer();    cout << "_____________________________________" << endl;    system("pause");    return 0;}

输出结果如下:
这里写图片描述
通过结果我们可以看出来调用顺序符合我们开始写的析构链。

这里的函数调用必须有个动态绑定,要实现这种动态绑定必须满足两个条件:

父类指针在进行析构时,函数调用必须有个动态绑定,要实现这种动态绑定\
必须满足两个条件:
(1). 只有指定为虚函数的成员函数才能进行动态绑定.
(2). 必须通过基类类型的指针或者引用进行函数调用.

产生这种不同的主要原因是,当父类析构函数没有被virtual修饰时,\
也就是说在delete父类指针时不会对函数进行动态绑定,而是根据父\
类指针的静态类型(声明时类型),进行函数调用,这里自然先调用\
父类的析构函数,根据我们的析构链可以知道:父类析构函数不会调\
用子类析构函数,因此我们测试程序一的只调用了父类析构函数。当\
父类函数被virtual修饰时,这里进行函数调用时会进行动态绑定,也\
就是调用指针实际指向的对象的方法,由于父类指针指向了子类对象\
这里自然就调用到了子类的析构函数,接下来就按照我们的析构链执\
行了。

1 0