首页 > 编程语言 > 详细

Effective C++ Notes

时间:2015-06-27 16:17:02      阅读:174      评论:0      收藏:0      [点我收藏+]

Item 07 : 为多态基类声明virtual析构函数

技术分享
 1 #include <iostream>
 2 using namespace std;
 3 
 4 class Base {
 5 public:
 6     Base() : bValue(1) {}
 7     virtual ~Base() { cout << "Base destructor" << endl; }
 8     // ~Base() { cout << "Base destructor" << endl; }
 9     virtual void print() {
10         cout << "print : base" << endl;
11     }
12 private:
13     int bValue;
14 };
15 
16 class Derived : public Base {
17 public:
18     Derived() : dValue(100) {}
19     ~Derived() { 
20         cout << "Derived destructor" << endl; 
21     }
22     void print() {
23         cout << "print : derived" << endl;
24     }
25 private:
26     int dValue;
27 };
28 
29 int main() {
30     Base* p = new Derived();
31     p->print();
32     delete p;
33 }
View Code

 注意Line 7和8,当基类的析构函数用的是Line7, 即基类析构函数是virtual时,Line32处执行delete p时,相当于调用p所指的析构函数,由于p是一个指向派生类对象的基类指针,且基类中析构函数是virtual的,所以满足了多态的发生条件,即此处调用的是派生类的析构函数Line19。派生类在析构的时候会自动调用其基类的析构函数,所以就有了下图的结果。 

技术分享

假如基类的析构函数不再是virtual的 (即将Line7注释掉,换成Line8),这样在Line32处调用delete p时, p本身是个基类指针,但是所指向的又是一个派生类对象。此时如果p所调用的函数是virtual的,那么p就直接调用派生类中的同名函数,即上面所描述的那样;若p所调用的函数不是virtual的,那它就老老实实的调用基类的函数。

所以将基类的析构函数换成non-virtual之后(即注释掉Line7换成Line8之后),结果如下:

技术分享

 这样导致的结果就是p所指的派生类对象只有基类部分得到释放,派生类对象中独属于派生类的部分仍留在堆上,导致内存泄漏。

 ==========================================================================================================

 

技术分享
 1 #include <iostream>
 2 using namespace std;
 3 
 4 class Point {
 5 public:
 6     Point(int xCoord, int yCoord);
 7     ~Point();
 8 private:
 9     int x, y;
10 };
11 
12 class Point2 {
13 public:
14     Point2(int xCoord, int yCoord);
15     virtual ~Point2();
16 private:
17     int x, y;
18 };
19 
20 class Point3 {
21 public:
22     Point3(int xCoord, int yCoord) : x(xCoord), y(yCoord) {}
23     ~Point3() {}
24 private:
25     int x, y;
26 };
27 
28 int main() {
29     cout << sizeof(Point) << endl;
30     cout << sizeof(Point2) << endl;
31     Point* p;
32     Point3 obj(1,2);
33     return 0;
34 }
View Code

这段代码想要表达两个问题:

1. 虚函数由于vptr,vtbl,会占用一些额外空间。Point和Point2的差别就在于析构函数是否是virtual,输出结果为8,12.

2. 我把Point3这个class放在这的目的是想说明,对于Point和Point2这样的,类内部的构造函数、析构函数只有声明没有定义(都直接以;结尾的),在其成员函数-没有定义的情况下不妨碍对它们求sizeof和定义指针(L31),但是它们不能定义对象(像L32那样)。

 

Effective C++ Notes

原文:http://www.cnblogs.com/forcheryl/p/4604039.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!