條款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》