Effective C++ 第七彈 45-50

 

條款45:清楚知道C++默默爲我們完成和調用哪些函數

如果你這麼寫

class Empty();

其意義相當於:
class Empty
{
public:
Empty();
Empty(const Empty& rhs);
~Empty();

Empty& operator=(cosnt Empty& rhs);
Emtpy* opertor&();
const Empty* operator&() const;
};

經過編譯器處理後,這些函數實際上被定義成這樣:

inline Empty::Emtpy(){}
inline Empty::~Emtpy(){}
inline Empty* Empty::operator&(){ return this; }
inline const Empty* Empty::operator&() const { return this; }
1、會爲我們聲明一個copy構造函數,一個虛構函數,一個assignment運算符和一個取地運算符;

2、默認的構造函數和析構函數不做任何事情,而且析構函數並非虛擬函數;

3、缺省的取址運算符只負責傳回對象地址。

4、對於copy constructor或assignment運算符,官方規則是: 
     缺省的copy constructor(或assignment)對class的nonstatic data members執行memberwise copy constructor。
   如果m是class C中的一個型別T的nonstatic data member,而c沒有聲明copy constructor或assignment,那麼就調用T的copy constructor   或assignment,直到遇到一個copy constructor或assignment或是遇上內建型別(如int,double)。
     缺省情況下,內建型別以bitwise copy方式進行copy constructor或assignment。

5、如果你打算讓一個內含"reference member"或"const member"的class支持assignment動作,你必須自己定義assginment運算符。

why?看下面兩個程序:

程序一、

template<class T>  
class NamedObject  
{  
public:  
    NamedObject(string& name, const T& value):nameValue(name),objectValue(value){};

     //這個形式和編譯器自動爲我們生成的是一致的,即對所有成員變量調用拷貝構造函數。
private:  
    string& nameValue;  
    const T objectValue;  
}; 

程序二:

template<class T>  
class NamedObject  
{  
public:  
    NamedObject(string& name, const T& value):nameValue(name),objectValue(value){};  //同上,對引用也用相同動作
private:  
    string& nameValue;  
    const T objectValue;  
};  
 
 
int main()  
{  
    string newDog("Persephone");  
    string oldDog("Satch");  
    NamedObject<int> p(newDog, 2);   //p的nameValue已經被賦值了
    NamedObject<int> s(oldDog, 29);   //使得p的nameValue再次被賦值,這對引用是不允許的。
    p = s;  
    return 0;  
}

6、如果base classes將標準assignment運算符聲明爲private,編譯器也會拒絕爲其derived class產生assignment運算符,因爲子類的assignment也必然調用父類的assignment,而父類該運算符是無法訪問的。

條款46:寧願編譯和連接時出錯,也不要執行時才錯

以"編譯期檢驗"取代了"執行期檢驗"。

程序:

class Month {
public:
  static const Month Jan() { return 1; }
  static const Month Feb() { return 2; }
  ...
  static const Month Dec() { return 12; }
  int asInt() const          

  { return monthNumber; }
private:
  Month(int number): monthNumber(number) {}
  Month(const Month& rhs);
  const int monthNumber;
};
class Date {
public:
  Date(int day, const Month& month, int year);
  ...
};

Adventage:

第一:構造函數私有化阻止clients產生新的月份。
第二:const使它們不可能被修改。
第三:獲得Month object的唯一途徑調用函數,不用擔心Month object沒有被初始化。

條款47:使用non-local static objects之前先確定它已有初值

何爲non-local static objects

1、定義域global或namespace scope;

2、在某個class內聲明爲static;

3、在某個file scope內定義爲static

解決辦法:

C++對於何時初始化一個non-local static object沒有任何明確表示,但卻非常明白地指出函數中的static object(local static object)的初始化時機:在此函數被調用期間第一次遭遇此對象之定義時。如果不直接存取non-local static objects,而是改爲調用函數(傳回一個references,指向函數內的local static objects),你便能夠保證,你獲得的reference一定指向已經初始化妥當的對象。

條款48:不要對編譯器的警告信息視如不見

廢話

條款49:儘量讓自己熟悉C++標準程序庫

STL

條款50:加強自己對C++的瞭解

《The Design and Evolution of C++》《The Annotated C++ Reference Manual》

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章