标签:
C++明确指出:当派生类对象是由一个基类指针释放的,而基类中的析构函数不是虚函数,那么结果是未定义的。其实我们执行时其结果就是:只调用最上层基类的析构函数,派生类及其中间基类的析构函数得不到调用。
1 #include <iostream> 2 3 using namespace std; 4 5 class TimeKeeper 6 { 7 public: 8 TimeKeeper(); 9 ~TimeKeeper(); 10 }; 11 TimeKeeper::TimeKeeper() 12 { 13 cout << "Construct TimeKeeper" << endl; 14 } 15 TimeKeeper::~TimeKeeper() 16 { 17 cout << "Destruct TimeKeeper" << endl; 18 } 19 20 class WristWatch : public TimeKeeper 21 { 22 public: 23 WristWatch(); 24 ~WristWatch(); 25 }; 26 WristWatch::WristWatch() 27 { 28 cout << "Construct WristWatch" << endl; 29 } 30 WristWatch::~WristWatch() 31 { 32 cout << "Destruct WristWatch" << endl; 33 } 34 35 int main() 36 { 37 TimeKeeper* pt = new WristWatch; 38 delete pt; // 仅调用TimeKeeper::~TimeKeeper 39 40 return 0; 41 }
现在我们将基类的析构函数变为虚析构,代码只改动一行,在~TimeKeeper()前面加上virtual,那么用基类指针释放派生类对象时,就会先调用WristWatch::~WristWatch,然后调用TimeKeeper::~TimeKeeper。
注意:
1> 如果在定义一个类时可以确保该类不会作为多态的基类,那么不要为其定义虚析构函数。因为虚函数的实现机制会增大对象的空间(必须保存一个指向vtable的vptr指针,会占用32bit或者64bit的存储空间)。因此,经验是:只有当一个class中至少含有一个virtual函数,才为其定义virtual析构函数。
2> 不要从non-virtual析构函数的类型继承。
有时候让一个类带有pure virtual析构函数更便利一些:
1 class Base 2 { 3 public: 4 virtual ~Base() = 0; // pure virtual destructor 5 }; 6 Base::~Base() // definition 7 { 8 9 }
主要有两方面的好处:
1> 你想拥有一个抽象类(接口),但还没找到任何有用的virtual函数可供使用
2> 同时解决了多态的析构调用问题。
但此时你必须注意:必须为这个pure virtual析构函数提供一个实现。因为在析构过程中,编译器会在派生类的析构函数中调用基类的析构函数,如果没定义,则必然发生错误。
总结:
标签:
原文地址:http://www.cnblogs.com/benxintuzi/p/4525881.html