0%

为什么父类的析构函数要声明为虚函数?

为什么C++中,父类的析构函数要声明为虚函数?下面让我们测试一下。

1.当父类析构函数为非虚函数时

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
#include <iostream>

using namespace std;

class Parent
{
public:
Parent()
{
cout << "Parent construct." << endl;
}

~Parent()
{
cout << "Parent deconstruct." << endl;
}
};


class Child: public Parent
{
public:
Child()
{
cout << "Child construct." << endl;
}

~Child()
{
cout << "Child deconstruct." << endl;
}
};

int main(int argc, char** argv)
{
Parent* p = new Child();
delete p;

cout << "==========" << endl;

Child* c = new Child();
delete c;
}

输出:

1
2
3
4
5
6
7
8
Parent construct.
Child construct.
Parent deconstruct.
==========
Parent construct.
Child construct.
Child deconstruct.
Parent deconstruct.

当父类指针指向子类对象时,析构过程不会调用子类的析构函数。此时若子类构造函数中有申请内存空间,则将无法被释放,导致内存泄漏。

2.当父类析构函数为虚函数时

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
#include <iostream>

using namespace std;

class Parent
{
public:
Parent()
{
cout << "Parent construct." << endl;
}

virtual ~Parent()
{
cout << "Parent deconstruct." << endl;
}
};


class Child: public Parent
{
public:
Child()
{
cout << "Child construct." << endl;
}

~Child()
{
cout << "Child deconstruct." << endl;
}
};

int main(int argc, char** argv)
{
Parent* p = new Child();
delete p;

cout << "==========" << endl;

Child* c = new Child();
delete c;
}

输出:

1
2
3
4
5
6
7
8
9
Parent construct.
Child construct.
Child deconstruct.
Parent deconstruct.
==========
Parent construct.
Child construct.
Child deconstruct.
Parent deconstruct.

当父类指针指向子类对象时,析构过程先调用子类析构函数,再调用父类析构函数。

3.总结

若一个类的析构函数为非虚函数,不管该类的指针是指向自己、还是指向子类,析构过程都是直接调用该类的析构函数,此时若该类指针指向子类对象,则有问题。
若一个类的析构函数为虚函数时,不管该类的指针是指向自己、还是指向子类,析构过程会调用实际指向对象的析构函数,若指向子类对象,则调用子类析构函数(子类析构函数调用完,再调用父类析构函数),若指向父类对象,则调用父类析构函数。