Tip01:C++爲一個語言聯邦
C:C++是以C爲基礎,這一部分就是基礎的C,沒有模板(template),沒有異常(exceptions),沒有重載(overloading)
Object-Oritented C++:即C with Class,面向對象部分。
Template C++:C++的泛型編程
STL:一個template程序庫。
編程守則:
1.對於C而言,因爲C中沒有Object的概念,因此值傳遞(pass-by-value)比引用傳遞(pass-by-reference)高效。
2.對於Object-Oritented C++和Template C++,由於有了構造函數和析構函數的存在,pass-by-reference-to-const更好
3.對於STL,因爲迭代器和函數對象都是在C指針上構建的,所以舊式的C pass-by-value再次適用
Tips02:儘量以const,enum,inline代替#define
一、原因一:#define使用的名稱可能未進入記號表(symbol table),導致調試困難。
二、enum hack的用法。
在某些舊式編譯器上,可能不允許static成員在其聲明式上獲得初值。當然,可以將初值放在定義式上。
然而,class編譯期間需要一個class常量。如
class GamePlayer{ private: static const int NumTurns = 5; int scores[NumTurns]; }
如果編譯器不通過static const int NumTurns = 5;就需要用到enum hack。
class GamePlayer{ private: enum {NumTurns = 5}; int scores[NumTurns]; }
補充一點,初始化static成員變量。在頭文件,類定義中聲明static變量
static T sMember
然後在源文件(.cpp)定義該static變量
T Class::sMember = value
三、#define定義的函數宏,最好用inline+tepmlate替代
#define CALL_WITH_MAX f((a) > (b) > (a) : (b)) int a = 5 , b = 0; CALL_WITH_MAX(++a, b) a = 7; CALL_WITH_MAX(++a, b+10) a = 6;
a的遞增次數取決於和誰比較。
①++a,b。++a=6,a>b,返回(++a),a = 7;
② ++a,b+10。++a=6,a<b+10,返回(b), a = 6
Tip03:儘可能使用const
一、成員函數是const的含義,Class::Function() const。
1.bitwise constness:成員函數不能改變任何成員變量,也就是說不能更改對象的任何一個bit。
但是如果,成員變量是指向對象的指針,按照bitwise的觀點,成員函數不能改變該指針,相當於在該成員函數內,指針是指針常量。然而,在const成員函數內,卻可以改變指針指向的對象。
但是,const成員函數的初衷,就是防止改變指針指向的對象。
PS:編譯器就是bitwise constness
2.logical constness:const成員函數可以修改成員變量,但只有編譯器通過的情況下。
既然成員函數是const,對於編譯器而言,它就絕不能修改成員函數,如何讓它能通過編譯器檢查呢?在成員變量添加修飾符mutable,可以釋放掉成員變量的bitwise constness約束。也就是說,即使在const成員函數內,也可以修改mutable成員變量。
二、non-const版本調用const版本。
通常const版本的non-const的函數實現是一樣的,唯一的不同是返回類型。這時,我們可以在non-const版本調用const版本。
①將(*this)轉換爲const類型static_cast<const T>(*this)。這樣就才能調用const版本的函數
static_cast<const T&>(*this).function()
②將const版本的返回值(const T&)轉換成non-const。
const_cast<T &>( static_cast<const T&>(*this).function())//(*this)返回的是reference of T
三、爲什麼non-const版本不能調用const版本
const成員函數絕對不會改變對象的邏輯狀態(logical state),但non-const成員函數卻沒這條限制。如果const版本調用non-const版本,就會發生const函數內改變了對象的邏輯狀態,不管實際上有沒有改變,這完全取決於non-const版本
Tip04:確定對象被使用前初始化
一、賦值(assignment)和初始化(initialization)的區別
XXX::XXX(){ Member1 = xxx; Member2 = xxx; }
這叫賦值。而Java中不存在初始化列表,因此只能採用這種初始化方式,所以在Java的初始化對應的是C++的賦值
二、初始化的順序
類的成員變量總是以其聲明的方式被初始化。即類中聲明的順序是A,B,C,D…,那即使初始化列表的順序是B(xxx),D(xxx),C(xxx),A(xxx),實際初始化順序依然是A,B,C,D
三、什麼是non-local static對象。
一般聲明在函數內部的變量,稱之爲局部變量或者本地(local)變量。所以,non-local static對象,就是在函數體之外聲明的static對象
四、non-local static對象的初始化順序。
對於把不同的編譯單元內的non-local static對象的初始化順序根本,沒有明確定義。
五、如果其他類用到了non-local static對象,但不能確定該對象是否初始化,怎麼解決。
用local static對象替換non-local static對象。C++保證,函數內的local static對象會在“該函數被調用期間”“首次遇到該對象之定義式”時被初始化。用函數調用(返回一個reference指向local static對象)替換non-local static對象,那麼該reference一定指向了一個歷經初始化的對象