第一部分:有指針成員數(shù)據(jù)的類
- 概述:成員數(shù)據(jù)有指針季眷,在設(shè)計類時需要注意拷貝構(gòu)造,拷貝賦值和析構(gòu)的實現(xiàn)方式
- 編譯器會生成默認(rèn)的拷貝構(gòu)造和拷貝賦值函數(shù)卷胯,但僅僅是對指針成員的復(fù)制子刮,這樣的構(gòu)造和賦值會導(dǎo)致內(nèi)存泄漏問題
- 三大函數(shù)
1. 析構(gòu)函數(shù)
- 需要釋放指針?biāo)赶虻膶ο?br> 2. 深拷貝和淺拷貝
- 深拷貝:不僅拷貝指針并拷貝指針指向的內(nèi)容
3. 拷貝構(gòu)造函數(shù):String s2(s1)
4. 賦值構(gòu)造函數(shù):String s2=s1
- 檢查是否自我賦值
- 釋放s2中指針?biāo)赶虻膬?nèi)容
- 為s2開辟足夠大的空間
- 將s1的內(nèi)容拷貝到s2中
5. String類的<<運算符重載(屬于復(fù)習(xí)內(nèi)容)
- 是否可以定義成成員函數(shù)?這樣做好不好窑睁?(寫成成員函數(shù)挺峡,會與傳統(tǒng)用法不一致) - 堆葵孤,棧和內(nèi)存管理
1. Stack:存在于某作用域的一塊內(nèi)存空間
2. Heap:又操作系統(tǒng)提供的一塊global內(nèi)存空間,程序可以動態(tài)分配從中獲取若干區(qū)域
3. Stack object:在作用域中定義的變量橱赠,生存期在作用域結(jié)束之際結(jié)束尤仍,又稱為auto object
4. Static local object:生存期在作用域結(jié)束之后仍然存在,直到整個程序結(jié)束
5. global object:生存期在整個程序結(jié)束之后才結(jié)束
6. heap object
- 用new和delete開辟和釋放內(nèi)存空間
- Complex類(成員函數(shù)沒有指針)的new和delete過程
- String類(成員函數(shù)沒有指針)的new和delete過程
7. static
- 靜態(tài)函數(shù)狭姨,不會隱藏有this指針
- static成員數(shù)據(jù)定義吓著,在類外
- double Account::m_rate = 8.0 (可以不賦值,也可以賦值) - 隨筆:
1. 在類函數(shù)中送挑,可以寫明this绑莺,可以讓編譯器加this
第二部分:組合與繼承:
概述:學(xué)習(xí)了class(帶指針和不帶指針)的設(shè)計方法,可以利用類和類的各種關(guān)系解決實際問題惕耕,概況起來類和類有:
1. 復(fù)合(composition)
2. 委托(delegation)
3. 繼承(inheritance)-
復(fù)合
1. 從內(nèi)存的角度解釋復(fù)合關(guān)系:如:圖1
2. 復(fù)合關(guān)系下的構(gòu)造與析構(gòu):
- 構(gòu)造過程由內(nèi)而外
- 析構(gòu)過程由外而內(nèi) -
委托:如圖 2
1. 圖2非常有名的設(shè)計模式:handle/body 或 implement by pointer
2. String類有一個指向StringReq的指針纺裁,StringReq實現(xiàn)實際的功能,StringReq的改變不影響用戶使用String(編譯防火強(qiáng)司澎,String不用重復(fù)編譯)
-
繼承:表示is-a的關(guān)系
1. 繼承和虛函數(shù)搭配才有價值
2. 繼承的內(nèi)存表示:如圖3
3. 構(gòu)造:由內(nèi)而外(先父類再子類)
4. 析構(gòu):有外而內(nèi)(先子類再父類) -
繼承和虛函數(shù)
1. 成員數(shù)據(jù)的繼承:從內(nèi)存角度理解
2. 成員函數(shù)的繼承:從調(diào)用權(quán)理解
3. 成員函數(shù)分類:
- non-virtual函數(shù):不希望繼承類重新定義
- virtual函數(shù):希望繼承類重新定義(override)欺缘,而且有默認(rèn)定義
- 純虛函數(shù):希望繼承類一定要重新定義,沒有默認(rèn)定義(其實可以有定義挤安,屬于高級用法)
4. 繼承和虛函數(shù)的例子:template method設(shè)計模式谚殊,如圖4