條款1 視c++為乙個語言聯邦
今天的c++已經是個多重范型程式語言,乙個支援過程形式、物件導向形式、函式形式、泛型形式、元程式設計形式的語言。為了理解c++,必須認識其主要的次語言,總共4個:
1.c2.object-oriented c++
3.template c++
4.stl
條款2 盡量以const, enum, inline替換#define(即寧可以編譯器替換預處理器)
1.#define aspect_ratio 1.653
aspect_ratio沒有進入編譯器的symbol table,錯誤資訊會提到1.653而不是aspect_ratio,這樣查詢這個符號就會花費時間,所以應該這樣:
const double aspectratio = 1.653
有兩種特殊情況:
一。第一常量指標。應該寫為:const char* const authorname = "scott meyers";
二。class專屬常量。為了確保次常量最多只有乙份實體,必須讓它成為乙個static成員。通常c++要求你對所使用的任何東西提供乙個定義式,但如果它是class專屬常量又是static且為整數型別(int, char, bool),則需要特殊處理:只要不去它們的位址,可以宣告並使用它們而無需提供定義式。
class gameplayer
2.#define常用來實現巨集,看起來像函式,但是不會導致函式呼叫的開銷class testclass;
//const double testclass::d = 1.2; //此時不能加static,static只用於宣告,此處是定義;同理,不能在定義靜態函式時加上static;但是改法則不適用於全域性static 函式
如果編譯器不支援static整型常量在class內的初值設定,可改用所謂的「the enum hack」補償做法。
class gameplayer;
int scores[numtruns];
};
#define call_with_max(a,b) f((a)>(b)? (a):(b)) //以a和b中的最大值呼叫函式f
int a = 5, b = 0;
call_with_max(++a, b); //a被累加兩次
call_with_max(++a, b+10); //a被累加一次
可以使用template inline來替代上述表示://template可以實現和引數型別無關,inline可以消除函式呼叫的開銷
templateinline void callwithmax(const t&a, const t& b)
有了const, enum 和inline,只能降低對預處理器的需求,但不能完全消除,#include是必需品,而#ifdef/#ifndef在控制編譯中扮演重要角色
條款3 盡可能使用const
1. 注意:
如果被指物為常量,有兩種寫法:
const int* cpi;
int const* cpi;注意不是int *const cpi;
2. const成員函式
將const實施於成員函式的目的,是為了確認該成員函式可作用於const物件。該類函式比較重要,因為:一,得知哪個函式可以改動物件內容哪個不行很重要;二,使操作const物件成為可能(條款20說,改善c++程式效率的乙個根本方法是以pass by reference-to-const方式傳遞物件,而此技術可行的前提是,我們有const成員函式可用來處理取得的const物件)許多人漠視一件事實:兩個成員函式如果只是常量性不同,可以被過載,這是乙個重要的c++特性:
class testblock
char& operator(size_t position)
private:
string text;
};
void print(const textblock* ctb)
void print()
const成員函式的兩個陣營:
一是bitwise(又稱為physical constness),認為成員函式不能更改物件內的任何乙個bit,不幸的是許多成員函式雖然不十足具備const性質卻能通過bitwise測試,也就是說,乙個更改了指標所指物的成員函式雖然不能算是const,但如果只有指標(而非其所指物)隸屬於物件,那麼稱此函式為bitwise const不會引發編譯器異議。
class ctextblock
private:
char* ptext;
}const ctextblock cctb("hello");
char* pc = &cctb[0];
*pc='j' //雖然呼叫了const函式,沒有改變內部成員變數,但返回的指標最終還是導致改變了成員的值
二是logical constness,主張乙個const成員函式可以修改它所處理物件內的某些bits:class ctextblock;
std::size_t ctextblock::length() const
};2.在const和non-const成員函式中避免重複
上述的實現中兩個相互過載的函式造成了**的重複,為了實現**復用,可以使用non-const版本呼叫const版本:class textblock
char& operator (std::size_t position)
}; 上述**有兩次型別轉換,第一次用來為*this新增const(這使接下來條用operator時得以呼叫const版本);第二次則是從const operator返回值中移除const;更值得了解的是,
反向做法------令const版本呼叫non-const版本以避免重複是不應該的。const成員函式承諾絕不改變其物件的邏輯狀態,non-const成員函式卻沒有這般承諾。如果在const函式
呼叫non-const函式:你曾經承諾不改動的那個物件被改動了。實際上若要令這樣的**通過編譯,你必須使用乙個const_cast將*this身上的const性質解放掉(????)
Effective C 讀書筆記 1
1.定義式是編譯器對此物件撥發記憶體的地點。2.explicit宣告的建構函式可被用於禁止編譯器執行非預期的型別轉換。注 對於單個引數的建構函式定義了從該形參型別到該型別的乙個 轉換。explicit只對建構函式起作用,用來抑制隱式轉換。class a int function a a 當呼叫 fu...
Effective C 讀書筆記1
tmp 模板元程式設計 0.explicit建構函式比non explicit建構函式好。1.可以用const 來代替 define 定義乙個常量。define沒有作用域,也沒有封裝性。class a const int a num num的定義。在宣告式中已經獲初值,所以無需在定義式給初值。當在類...
Effective C 讀書筆記1
tmp 模板元程式設計 0.explicit建構函式比non explicit建構函式好。1.可以用const 來代替 define 定義乙個常量。define沒有作用域,也沒有封裝性。但enum不可以取位址,而const 常量能取位址。因此指標或引用不能指向enum常量。define定義巨集時,可...