1. 程式人生 > >C++ 程式設計思想(第一卷)閱讀總結

C++ 程式設計思想(第一卷)閱讀總結

最近工作閒翻閱了之前買f《C++程式設計思想》這裡貼上我認為對我最有幫助的部分,一來留給自己複習看,另一方面也和小夥伴們分享下:

預備知識―程式的記憶體分配 
一個由c/C++編譯的程式佔用的記憶體分為以下幾個部分 
1、棧區(stack)―   由編譯器自動分配釋放 ,存放函式的引數值,區域性變數的值等。其操作方式類似於資料結構中的棧。 
2、堆區(heap) ―   一般由程式設計師分配釋放, 若程式設計師不釋放,程式結束時可能由OS回收 。注意它與資料結構中的堆是兩回事,分配方式倒是類似於連結串列,呵呵。 
3、全域性區(靜態區)(static)―,全域性變數和靜態變數的儲存是放在一塊的,初始化的全域性變數和靜態變數在一塊區域, 未初始化的全域性變數和未初始化的靜態變數在相鄰的另一塊區域。 - 程式結束後有系統釋放 


4、文字常量區  ―常量字串就是放在這裡的。 程式結束後由系統釋放 
5、程式程式碼區―存放函式體的二進位制程式碼。

1 OPP相關

1.1、每個物件都有一個型別,OOP中class 和type是同義詞,在面向物件的程式設計中,我們所做的工作實際上就是創造新的資料型別,程式設計師定義class 是為了與具體問題相適應,而不是被迫適用已存在的資料型別。

1.2、當用<>來指定檔案時,前處理器以特定的方式來尋找檔案,一般是環境中或者編譯器命令指定的某種尋找路徑;當採用""指定檔案時,通常是從當前目錄開始尋找,如果檔案沒有找到則按<>方式進行尋找。

2 C++總的C

2.1、整數類型範圍從小到大為:short int->int->long int。

         浮點類型範圍從小到大為:float->double->long double;

         unsigned 數不儲存符號,因此有一個多餘的位可用,所以它能儲存比signed數大兩倍整數

2.2、main()的內部和外部定義的變數存放在不同的區域;資料和函式也存在不同區域

2.3、C++程式設計的一般原則是在定義時進行初始化,const 變數必須有初始值

2.4、enum可以提高程式清晰度,採用union可以節省記憶體,所有union 變數地址都是一樣的

2.5、 採用前處理器來完成程式碼除錯功能,具體實現如下:

#define NDEBUG 
//......
#ifdef NDEBUG
/* debugging code here*/
......
#endif
2.6、C++允許將任何型別的指標賦給void* ,但是不允許將void* z指標賦值給其他任何型別的指標。

2.7、同文件是我們和庫使用者之間的合約,合約描述了庫中的資料結構,為函式呼叫規定了引數和返回值,標頭檔案中只限於申明,為了避免標頭檔案的內容的多次申明,我們可以採用如下方式避免:

#ifndef HEADER_FLAG
#define HEADER_FLAG
//Type declaration here
.....
#endif
同樣為了避免名稱空間的錯亂,標頭檔案中絕不會看到using

2.8、如果程式設計師想允許顯式讓不屬於當前結果的一個成員函式訪問當前結構的物件時,可以藉助friend 修飾符,friend 必須在一個結構內部宣告

3 、C++特色:

3.1、class與struct 的區別在於class的成員預設是private,而struct的成員預設是public;

3.2、C++的安全性體現在初始化和清除兩個方面,用建構函式確保初始化,用解構函式確保清除

3.3、C++中巨集被行內函數(inline function)代替,這樣既保證了高效性(成員函式和前處理器巨集一樣高效)也保證了安全性(當呼叫行內函數時,編譯器首先確保呼叫正確,即所有的引數型別都滿足,巨集定義在預處理中,不能進行檢查)。

任何在類中定義的函式都自動的成為行內函數;

使用行內函數的目的是減少函式呼叫的開心,但是如果函式交大,由於需要在呼叫函式的每一處重複賦值程式碼,這樣會使得程式碼膨脹,因此小函式作為行內函數比較理想

3.4、static使得變數存於靜態資料區中,而不是堆疊中。全域性靜態物件的建構函式在main()之前呼叫,並且在退出main()後呼叫解構函式;

3.5、 關鍵字namespace如何class、struct、enum和union一樣把它們的成員的名字放到不同的空間去,但namespace與class 、struct、union和enum有著明顯的區別:

        (1)namespace只能在全域性範圍內定義,但他們之間可以相互巢狀;

        (2)namespace定義的結尾不必跟著分號;

(3)一個namespace可以在多個頭檔案中用一個識別符號來定義;

(4)不能像class一樣去建立一個名字的例項;

(5)namespace可以用另一個名字作為他的別名;

3.6、 & 在C++表示引用,引用可以理解為一個奇特的指標,這個指標的優點是不必懷疑它是否初始化,引用的使用規則如下:

(1)應用建立是必須初始化;

(2)一個引用指向一個物件後不可轉變為另一個物件的引用;

(3)不能NULL的引用

最經常看見引用的地方是函式引數和返回值中,當引用被用作函式引數是,在函式內任何對引用物件的修改將在函式外引數發生變化,當然也可傳遞指標來做相同的事情,但引用具有更清晰的語法。

3.7、拷貝建構函式(copy-constructor)是一種特殊的建構函式,需要引用來實現從現有的相同型別的物件中產生新的物件。編譯器使用拷貝建構函式通過值傳遞的方式在函式中傳遞和返回物件

3.8、使用delete void * 可能會出錯,在刪除之前必須把它轉為適當的型別,否則將會丟失記憶體;

3.9、C++確保在進入新類的建構函式體之前呼叫酥油的其他的建構函式,這樣所有子物件的成員函式所做的任何呼叫總是轉到這個被初始化的物件中,

MyType::MyType(int i):Bar(i){///....}

4 C++ 中的多型

4.1、多型永遠發生在派生類中與基類之間,C++通過virtual函式和晚繫結(late binding)實現;

如果一個函式在基類中被申明為virtual ,那麼所有的派生類中它都是virtual,可以對基類中的虛擬函式進行重寫;

在每個帶有虛擬函式的類中,編譯器祕密放置了一個指標(vpointer)指向該物件的VTABLE(編譯器對每個包含虛擬函式的類建立一個表:VTABLE)


編譯器從Instrument指標開始,該指標指向該物件的起始地址,對於所有的Instrument或派生物件,他們的vptr都存在相同的位置(常常在物件的開頭),所以編譯器能夠取出該物件的vptr,vptr指向vtable的起始地址,所有的vtable都有相同的順序,如圖。play()第一個,what()第2個;

5、C++模板(template)

5.1、template告訴編譯器,隨後定義將錯做一個或者多個未指明的型別,當這個模板產生實際類程式碼時,必須指定這些型別使得編譯器可以替換他們。