为什么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.总结
若一个类的析构函数为非虚函数,不管该类的指针是指向自己、还是指向子类,析构过程都是直接调用该类的析构函数,此时若该类指针指向子类对象,则有问题。
若一个类的析构函数为虚函数时,不管该类的指针是指向自己、还是指向子类,析构过程会调用实际指向对象的析构函数,若指向子类对象,则调用子类析构函数(子类析构函数调用完,再调用父类析构函数),若指向父类对象,则调用父类析构函数。