Effective C++ 2

class A { public: A(); ~A(); A& operator=(const A& a); //复制的是non-static成员 A(const A&a); };

当自己声明了一个构造函数,则default构造函数将不会自动生成。
C++不允许reference改指向不同对象。
如果想要避免对象赋值,则可将赋值构造函数在private中声明。

 

接下来要讨论的是虚析构函数问题。

class TimeKeeper{
public:
 TimeKeeper();
 ~TimeKeeper();
 ...
};
class AtomicClock:public TimeKeeper{};
class WaterClock: public TimeKeeper{};
class WristWatch:public TimeKeeper{};

TimeKeeper *getTimeKeeper();  //function,返回指向TimeKeepr派生类。

TimeKeeper* ptk=getTimeKeeper();
delete ptk;   //调用~TimeKeeper();从而导致局部删除。
因此引入virtual析构函数。

virtual析构函数使用地点:当此类为基类时。
反之:被当做基类的类要保证析构函数析构正确,即要有virtual析构函数。

 

想要使类变为抽象类,最方便的方法可以是将析构变为pure virtual,并给出定义。

class DBConnection{ public: static DBConnection create(); void close(); }; //原始版本 class DBConn{ public: ~DBConn() { db.close(); } private: DBConnection db; }; //强制关闭版本 class DBConn{ public: ~DBConn() { try{db.close();} catch(...){abort();} } }; //忽略错误版本 class DBConn{ public: ~DBConn() { try{db.close();} catch(...){} } }; //最终版本 class DBConn{ public: void close() //给客户提供自行结束的函数。 { db.close(); closed=true; } ~DBConn() //如果客户不调用close,则自行结束(后果自负) { if(!closed){ try{db.close();} catch(...){} } } private: DBConnection db; bool closed; };

 

 

在构造函数和析构函数中不能调用virtual函数,不会像以上说的那样强。在此时,virtual就是一般函数。

类继承的声明过程,先调用基类构造函数,再派生类构造函数,再析构派生类,最后析构基类。

 

避免代码重复的办法,声明一个private函数init();将共有的代码放入。

 

令赋值操作符函数(成员函数)返回reference-to *this;以后会讲到,非成员函数的赋值函数不可以返回reference

class Widget { ... private: Bitmap*pb; }; Widget& operator=(const Widget& rhs) { if(rhs==&this) return *this; delete pb; //先删了,如果以下异常,则返回出问题。 pb=new Bitmap(rhs->pb); //仍无法解决new导致的异常。 return*this; } Widget& operator=(const Widget& rhs) { Bitmap* ptmp=pb; pb=new Bitmap(rhs->pb); //先new后delete,如果pb没new成功,保持原状。如果成功了,正常。 delete ptmp; return *this; } 接下来隆重介绍copy and swap技术。 void Widget::swap(Widget& rhs); Widget& operator=(const Widget& ths) { Widget temp(rhs); swap(temp); return *this; }

 

下面讲个笑话,如果你自己定义copying函数,则如果你出错,编译器为了报复,不会提醒你错误。

 

 

 

你可能感兴趣的:(Effective C++ 2)