析构函数什么情况下要定义为虚函数?
1 1.第一段代码 2 #include<iostream> 3 using namespace std; 4 class ClxBase{ 5 public: 6 ClxBase() {}; 7 ~ClxBase() {cout << "Output from the destructor of class ClxBase!" << endl;}; 8 void DoSomething() { cout << "Do something in class ClxBase!" << endl; }; 9 }; 10 class ClxDerived : public ClxBase{ 11 public: 12 ClxDerived() {}; 13 ~ClxDerived() { cout << "Output from the destructor of class ClxDerived!" << endl; }; 14 void DoSomething() { cout << "Do something in class ClxDerived!" << endl; }; 15 }; 16 int main(){ 17 ClxDerived *p = new ClxDerived; 18 p->DoSomething(); 19 delete p; 20 return 0; 21 }
22 运行结果: 23 Do something in class ClxDerived! 24 Output from the destructor of class ClxDerived! 25 Output from the destructor of class ClxBase! 26 这段代码中基类的析构函数不是虚函数,在main函数中用继承类的指针去操作继承类的成员,释放指针P的过程是:先释放继承类的资源,再释放基类资源. 27
28 2.第二段代码 29 #include<iostream> 30 using namespace std; 31 class ClxBase{ 32 public: 33 ClxBase() {}; 34 ~ClxBase() {cout << "Output from the destructor of class ClxBase!" << endl;}; 35 void DoSomething() { cout << "Do something in class ClxBase!" << endl; }; 36 }; 37 class ClxDerived : public ClxBase{ 38 public: 39 ClxDerived() {}; 40 ~ClxDerived() { cout << "Output from the destructor of class ClxDerived!" << endl; }; 41 void DoSomething() { cout << "Do something in class ClxDerived!" << endl; } 42 }; 43 int main(){ 44 ClxBase *p = new ClxDerived; 45 p->DoSomething(); 46 delete p; 47 return 0; 48 } 49 输出结果: 50 Do something in class ClxBase! 51 Output from the destructor of class ClxBase! 52 这段代码中基类的析构函数同样不是虚函数,不同的是在main函数中用基类的指针去操作继承类的成员,释放指针P的过程是:只是释放了基类的资源,而没有调用继承类的析构函数.调用dosomething()函数执行的也是基类定义的函数. 53 一般情况下,这样的删除只能够删除基类对象,而不能删除子类对象,形成了删除一半形象,造成内存泄漏. 54 在公有继承中,基类对派生类及其对象的操作,只能影响到那些从基类继承下来的成员.如果想要用基类对非继承成员进行操作,则要把基类的这个函数定义为虚函数. 55 析构函数自然也应该如此:如果它想析构子类中的重新定义或新的成员及对象,当然也应该声明为虚的. 56 57 3.第三段代码: 58 #include<iostream> 59 using namespace std; 60 class ClxBase{ 61 public: 62 ClxBase() {}; 63 virtual ~ClxBase() {cout << "Output from the destructor of class ClxBase!" << endl;}; 64 virtual void DoSomething() { cout << "Do something in class ClxBase!" << endl; }; 65 }; 66 class ClxDerived : public ClxBase{ 67 public: 68 ClxDerived() {}; 69 ~ClxDerived() { cout << "Output from the destructor of class ClxDerived!" << endl; }; 70 void DoSomething() { cout << "Do something in class ClxDerived!" << endl; }; 71 }; 72 int main(){ 73 ClxBase *p = new ClxDerived; 74 p->DoSomething(); 75 delete p; 76 return 0; 77 } 78 运行结果: 79 Do something in class ClxDerived! 80 Output from the destructor of class ClxDerived! 81 Output from the destructor of class ClxBase! 82 这段代码中基类的析构函数被定义为虚函数,在main函数中用基类的指针去操作继承类的成员,释放指针P的过程是:只是释放了继承类的资源,再调用基类的析构函数.调用dosomething()函数执行的也是继承类定义的函数. 83 84 如果不需要基类对派生类及对象进行操作,则不能定义虚函数,因为这样会增加内存开销.当类里面有定义虚函数的时候,编译器会给类添加一个虚函数表,里面来存放虚函数指针,这样就会增加类的存储空间.所以,只有当一个类被用来作为基类的时候,才把析构函数写成虚函数.
知识就是力量!