面向?qū)ο?Object Oritented
基于對(duì)象(Object Based) vs. 面向?qū)ο?Object Oritented)
- Object Based 面對(duì)的是單一 class 的設(shè)計(jì)(只有封裝厦取,即帶類(lèi)的C)
- Object Oritented 面對(duì)的是多重classes的設(shè)計(jì)阶女,classes 和 classes 之間的關(guān)系(繼承+多態(tài))
面向?qū)ο缶幊痰奶匦?features of OOP (A PIE)
- 抽象 Abstration
- 多態(tài) Polymorphism
- 繼承 Inheritance
- 封裝 Encapsulation
對(duì)象的構(gòu)成 an object consist of
- identity
- state
data fields(properties) with its current value - behaviors
functions
C++ Class 的兩種經(jīng)典分類(lèi)
- class without pointer members
- class with pointer members
重要概念梳理
1. const 關(guān)鍵字
C++中的const關(guān)鍵字的用法非常靈活,而使用const將大大改善程序的健壯性。
初始化和const
- const必須初始化蛇耀。
- 默認(rèn)情況下,const對(duì)象僅在文件(translation unit)內(nèi)有效。這一點(diǎn)和下文的inline類(lèi)似。
- 默認(rèn)情況下谷徙,編譯器在編譯時(shí)將用到該const對(duì)象的地方都替換成對(duì)應(yīng)的值。也就是說(shuō)每個(gè)文件都要有該const對(duì)象的定義驯绎。
- 如果想在多個(gè)文件之間共享const對(duì)象(在一個(gè)文件中定義const完慧,在其他文件中只是聲明)。解決的方法是聲明和定義都加上extern關(guān)鍵字剩失。
普通變量和const
const int n = 10屈尼;
n是一個(gè)只讀變量,程序不可以直接修改其值拴孤。這里還有一個(gè)問(wèn)題需要注意脾歧,即如下使用:int a[n];在A(yíng)NSI C中演熟,這種寫(xiě)法是錯(cuò)誤的鞭执,因?yàn)閿?shù)組的大小應(yīng)該是個(gè)常量,而n只是一個(gè)變量绽媒。
注:看到const關(guān)鍵字蚕冬,很多人想到的可能是const常量,其實(shí)關(guān)鍵字const并不能把變量變成常量是辕!在一個(gè)符號(hào)前加上const限定符只是表示這個(gè)符號(hào)不能被賦值。也就是它的值對(duì)于這個(gè)符號(hào)來(lái)說(shuō)是只讀的猎提,但它并不能防止通過(guò)程序的內(nèi)部(甚至是外部)的方法來(lái)修改這個(gè)值(C專(zhuān)家編程.p21)获三。也就是說(shuō) const變量是只讀變量旁蔼,既然是變量那么就可以取得其地址,然后修改其值疙教」琢模看來(lái)const也是防君子不防小人啊贞谓!:)
指針和const
-
const char * p
指向常量的指針(pointer to const) -
char * const p
常量指針(const pointer) -
const char * const p
指向常量的常量指針
訣竅:沿著號(hào)劃一條線(xiàn)限佩,如果const位于的左側(cè),則const就是用來(lái)修飾指針?biāo)赶虻淖兞柯阆遥粗羔樦赶驗(yàn)槌A克钔蝗绻鹀onst位于*的右側(cè),const就是修飾指針本身理疙,即指針本身是常量晕城。
頂層const和底層const
- 頂層const 對(duì)象本身是常量。對(duì)任何類(lèi)型都適合
- const int i = 10;
- char * const p = NULL;
- 底層const 所指的對(duì)象是常量(針對(duì)指針和引用等符合類(lèi)型)
- const int *p2 = NULL;
- const int &r = i;
cosnt對(duì)象拷貝
- 頂層const窖贤,不受影響
void func(const int i) // 既可以傳const int砖顷,也可以傳int
- 頂層const,必須有相同的底層const類(lèi)型赃梧,或者非const轉(zhuǎn)換成const(反之不行)
int i = 42;
const ci = 32;
const int *cp = &ci; // OK. 底層const類(lèi)型匹配
const int *cp = &i; // OK. int * 能轉(zhuǎn)換成 const int *
int * p = cp; // Error, 底層const類(lèi)型不匹配滤蝠,const int * 不能轉(zhuǎn)換成 int *
int &r = ci; // Error, 底層const類(lèi)型不匹配,int引用不能綁定到int常量上
void func(int *p);
func(&i); // OK.
func(cp); // Error. const int * 不能轉(zhuǎn)換成 int *
類(lèi)和const
-
const成員變量
class Foo { Foo(int x) :n(x) //只能在初始化列表中賦值 { } const int n; //成員常量不能被修改 }
-
const成員函數(shù)
class Foo { //不能改變對(duì)象的成員變量 //不能調(diào)用類(lèi)中任何非const成員函數(shù) void func() const; }
-
const類(lèi)對(duì)象/對(duì)象指針/對(duì)象引用
struct Foo { int func1() const {} int func2() {} }; int main() { const Foo f; f.func1(); f.func2(); //Error. const object can not invoke non-const member function! }
constexpr 和 const expression(常量表達(dá)式)
- const expression 值不會(huì)改變并且編譯過(guò)程中就能得到結(jié)果的表達(dá)式授嘀。
- const int max = 20; // 字面值一定是常量表達(dá)式
- int max = 20; //不是物咳。非const int
- const max = get_max(); // 不是。get_max運(yùn)行時(shí)知道結(jié)果
-
constexpr 變量 聲明為constexpr的變量必須一個(gè)常量表達(dá)式粤攒。
- 如果你認(rèn)定變量是一個(gè)常量表達(dá)式所森,聲明稱(chēng)constexpr類(lèi)型
const定義常量 代替 常量宏
- const定義的常量在程序運(yùn)行過(guò)程中只有一份拷貝
- 宏定義的常量在內(nèi)存中有若干個(gè)拷貝
2. inline vs. marco
相同點(diǎn)
消除函數(shù)調(diào)用的開(kāi)銷(xiāo)(參數(shù)壓棧、跳轉(zhuǎn)夯接、彈棧焕济、返回等指令操作)
不同點(diǎn)
-
macro 宏
- 預(yù)編譯階段。進(jìn)行
- 預(yù)編譯器進(jìn)行文本替換 textual substitution
- 無(wú)類(lèi)型盔几,無(wú)類(lèi)型安全檢查
- 不可調(diào)試
-
inline
- 編譯階段
- 編譯器在調(diào)用點(diǎn)內(nèi)聯(lián)展開(kāi)函數(shù)的代碼
- 編譯器必須在translation unit中找到inline函數(shù)的定義才能進(jìn)行展開(kāi)晴弃,因此inline函數(shù)應(yīng)該在頭文件中定義(只聲明沒(méi)用)
- 有類(lèi)型,類(lèi)型安全檢查
注意
- inline是對(duì)編譯器的請(qǐng)求⊙放模現(xiàn)代編譯器能夠根據(jù)函數(shù)的定義決定是否接受inline上鞠,甚至自動(dòng)inline一些沒(méi)有請(qǐng)求inline的函數(shù)
- 當(dāng)函數(shù)只有 10 行甚至更少時(shí)才將其定義為內(nèi)聯(lián)函數(shù)。濫用內(nèi)聯(lián)會(huì)導(dǎo)致代碼膨脹
binary size bloat
⌒旧ィ現(xiàn)代處理器由于更好的利用了指令緩存, 小巧的代碼往往執(zhí)行更快芍阎,因此代碼膨脹反而會(huì)增加開(kāi)銷(xiāo) - 簡(jiǎn)單的inline函數(shù)可以放在
.h
文件中,復(fù)雜的內(nèi)聯(lián)函數(shù)的定義, 應(yīng)放在后綴名為-inl.h
的頭文件中 - 定義在類(lèi)聲明之中的成員函數(shù)將自動(dòng)地成為內(nèi)聯(lián)函數(shù)
- constexpr自帶inline屬性
- 盡量使用inline取代macro
- assert是例外缨恒,assert是宏