五、了解c++默默编写并调用那些函数
class Empty() { }; //等同于 class Empty { public: Empty() // 默认构造函数 { } Empty(const Empty& rhs) //拷贝构造函数 { } ~Empty() // 析构函数 { } Empty&oprator=(const Empty& rhs) // 赋值运算符 { } }注意:编译器产生的析构函数是非虚的析构函数
六、不想使用编译器自动生成的函数,就应该明确拒绝如果想阻止拷贝行为,可以将相应成员函数声明为private并且不予实现
//Uncopyable .h #pragma once class Uncopyable { public: Uncopyable(); ~Uncopyable(); private: Uncopyable(const Uncopyable& unCopy); Uncopyable& operator=(const Uncopyable&); }; //Uncopyable.cpp #include "Uncopyable.h" Uncopyable::Uncopyable() { } Uncopyable::~Uncopyable() { } Uncopyable::Uncopyable(const Uncopyable& unCopy) { } Uncopyable& Uncopyable::operator=(const Uncopyable&) { Uncopyable newUncopy; return newUncopy; }总结 如果想阻止拷贝行为,可以将相应成员函数声明为private并且不予实现
七、多态基类声明virtual析构函数
1、带有多态性质的基类,应该声明一个虚析构函数。如果类带有任何虚函数, 那么这个类就应该有一个虚析构函数。 否则在父类指针指向子类对象的情况下,通过操作父类指针,可能无法释放子类对象 2、类的设计目的如果不是作为基类使用,或者不是为了多态性那么就不应该声明虚析 构函数 否则,对象体积会增加 补充:标准string是不带虚析构函数的 1、构造顺序 基类构造函数、对象成员构造函数、派生类本身的构造函数 2、析构顺序 派生类本身的析构函数、对象成员析构函数、基类析构函数(与构造顺序正好相反)
八、别让异常逃离析构函数 两个方法: 1、阻止异常从析构函数里传播出去,强迫程序结束 try { } catch { abort(); } 在Catch里记录异常信息,然后继续运行 2、双保险策略 封装一个释放函数,由用户释放,如果释放成功,那么在析构函数中不做处理 然后再析构函数中,做方法一的处理
九、绝不在构造析构过程中调用virtual函数 在derived对象的base class构造期间,对象的类型是base class而不是 derived class 十、令operator= 返回 reference to *this 现在string,vector,complex,std::shared_ptr等标准库类型的赋值运算符都返回*this