1.前言 大部分对象在使用之之后没有正确的从内存清理完毕,造成内存泄露也是C++出错的主要领域 引入类的析构是正确的从内存中清量类的对象 一般什么时候触发并调用类的析构函数呢? 答案是:当类实例对象超出它的有效作用域时,也就是撤消类对象时,自动调用析构函数来清理对象 构造函数用来初始化成员,析造函数则是用来清理对象 如我们删除一个类的指针对象,则自动调用析构函数: sales_item是一个类 sales_item *p = new sales_item //建立并分配一个类的指针p delete p;//这就是撤消类的对象,随后它自动调用析构函数 2.定义 构造函数名和类名完全一样,并在名字前面加"~"符号 每个类只有一个析构函数 2.1定义格式 ~析构函数名称(){} //一般析构函数: virtual ~析构函数名称(){} //虚析构函数: 代码如下 class item{ public: ~item(){} }; 3 基类与派生类 3.1一般基类是不用写出析构函数,编译器自动添加一个 类aa可以正常的工作就是编译器自动添加了四个函数 如代码 class aa{ public: //构造,析构,复制构造,赋值操作符四个函数由编译器自动添加 int getx(){return x;} void set(int a){x=a;} private: int x; };
3.2析构函数"三法则",如果类中有复制构造函数和赋值操作符重载,则析构函数必须要,三者缺一不可 class bb{ public: bb(const bb& rhs){...} //复制构造函数 bb& operator=(const bb& rhs){...} //赋值操作符 ~bb(){清理函数} //析构函数 private: int x }; 以上三个函数三者必须同时出现,以免出现有的对象清除不了,有的出现"浅复制错误"
3.3如果类中有指针成员,则必须专门写一个析构函数来清理指针成员,编译器默认添加的析构函数不会去清理指针对象 如果类中有指针成员,如链表结构实现等, 指针成员是基本单位,在方便使用指针的同时,如何管理好它们的工作就是C++中最困难的部分
这个析构函数最好特别定制,做法是析构函数加一个清理函数,析构函数直接调用它就OK
3.4派生类 虚成员函数和虚析构函数通常是成对出现 当基类有虚函数时,派生类会发生动态调用,也就是动态绑定, 当不知道是调用基类对象还是调用派生类对象时,还要正确的清理它们就更加困难啦,在基类引入虚析构函数后, 它也能发生动态绑定,正确的清理对象,这些都要到程序运行后才能知道调用对象,在编译前是无法知道对象是谁的 代码: //基类 class base{ public: virtual draw(){}; //虚方法 virtual ~base(){};//虚析构函数 };
//派生类 class dev : public base{ public: draw(){}//draw方法的实现 ~dev(){}//析构函数 };
4.设计指导 4.1一般的类我们不需要设计出它的析构函数,编译器自动为我们构建一个析构函数 4.2析构函数"三法则",如果类中有复制构造函数和赋值操作符重载,则析构函数必须要,三者缺一不可 4.3如果类中有指针成员,则必须专门写一个析构函数来清理指针成员,编译器默认添加的析构函数不会去清理指针对象 4.4"虚函数和虚析构函数成对实现", 当类中有虚成员时,定制虚析构函数,让派生类实行动态绑定方式来清除基类对象或者派生类对象
|