標籤:顯示 否則 餓漢 == 相同 穩定性 type 安全性 tin
一、拷貝建構函式
- 1、是一種特殊的建構函式,就是用一個已有的對象去構造其同類的副本對象,即對象複製
class 類名 { 類名(類名& that) { 對成員挨個賦值 } }
- 2、編譯器會預設產生一個拷貝建構函式
編譯產生的拷貝建構函式預設會逐位元組複製類中的每一個成員
如果在類A中有類B成員,會在類A的拷貝構造中自動調用類B的拷貝構造
- 3、程式員可以自訂拷貝構造來取代預設的拷貝構造
a、拷貝構造只能有一個,不能重載
b、一旦程式員自訂的拷貝構造,編譯器就不再產生
c、在自訂的拷貝中能通過編碼來實現成員的複製
- 4.一般情況下編譯器產生的拷貝構造完全夠用,不要輕易自訂構造
- 5.什麼情況下調用拷貝構造
a、對象與對象賦值
b、用對象與函數傳參
c、用對象當作傳回值
二、初始化列表
- 1、是一種成員的初始化方式,在建構函式的大括弧前使用小括弧對成員進行初始化的一種方式
class { 類名(參數列表):成員1(參數),成員2(參數).... { } }
a、參數列表可以解決建構函式的參數與成員重名的問題
b、參數列表會先與建構函式執行
- 2、如果類成員是數組,可以使用{}進行初始化
- 3、如果有成員是類,可以在初始化列表中顯示調用建構函式
- 4、如果成員中有const成員、引用成員,必須使用初始化列表
- 5、類成員的構造順序與初始化列表無關,而是與成員定義的順序有關
三、this指標
- 1、相同類型的對象各自擁有獨立的成員執行個體,彼此共用一份成員函數,成員函數是如何知道誰在調用它
- 2、為了讓成員函數知道是哪個對象在調用,並準確訪問到對象的成員,編譯器會自動為每個成員函數添加一個看不到的參數,這個參數就是指向調用對象的指標(this)
- 3、類中的所有成員函數都有this指標,包括構造、析構、拷貝構造等,只是構造中this指向的是正在被建立的對象
- 4、this指標預設情況下都是隱藏的(在成員函數中訪問成員變數時自動就加上了),但也可以顯示使用
- 5、使用方式使用this
a、區分成員變數與參數
b、把對象當作傳回值與其他對象進行互動
四、常對象與常函數
- 1、建立對象時添加const關鍵字,這個對象就不可再修改,就有了常屬性,故意味著整個對象中的所有東西都不能修改
- 2、常對象不能調用普通成員函數,調用成員函數就相當於把對象的this指標給了它,就會有被修改的風險
- 3、函數體前加const關鍵的叫常函數,常對象只能調用常函數,普通對象也可以調用常函數
常函數就相當於對this指標添加了const屬性
- 4、常函數與’非‘常函數會形成重載不會衝突
- 5、如果有成員確實需要修改,它又被const修飾,可以對成員添加一個關鍵字mutable,這樣即使常對象調用了常函數依然可以修改
五、解構函式
- 1、當對象被銷毀時自動調用的函數叫解構函式,對象的整個生命週期中只能被調用一次,它是對象被銷毀前的最後一個執行的動作
class 類名 { //不能重載,只能有一個 //不可以有傳回值,沒有參數 ~類名(void) { } };
- 2、編譯會預設產生一個解構函式,預設解構函式負責銷毀能看的到的成員,如果有成員是類,會自動調用成員的解構函式,類成員的析構過程和構造過程相反
- 3、解構函式雖然不能重載,但可以自訂,有自訂解構函式預設析構就不會產生
- 4、當類中有解構函式看不到的資源時, 有需要還原的設定時(把開啟的檔案關閉/把擷取的資料儲存),這時就需要自訂解構函式
六、賦值構造
- 1、賦值構造就是一個對象給另一個對象賦值的時候調用的函數
Student stu2 = stu1; //拷貝構造 void func(Studnet stu); //拷貝構造 func(stu1;) Student func(void) //拷貝構造 { return *this; } Student stu = func();
void operator = (Student& that) { } //可以與其他對象進行互動 Student operator = (Student& that) { }
- 3、編譯器會預設產生賦值構造,它的功能與拷貝構造的功能一樣,把對象A完全拷貝給對象B
- 4、賦值構造與拷貝構造的區別
拷貝構造:使用對象A去建立對象B(調用時對象B還未產生)
賦值構造:對象A與對象B都已經構造完成,此時B = A;
如果對象中有常成員,拷貝構造可以成功調用,但賦值構造不行
- 5、一般情況下預設的賦值構造基本夠用,除非有成員是指標,指向了額外的記憶體空間,這種情況下才需要自訂拷貝構造、賦值構造
- 6、自訂賦值構造
a、確定賦值構造的格式
b、防止自賦值
int num = 1;
num = num;
c、釋放舊資源
d、分配新的資源
e、拷貝新內容
//f、代碼利用(顯示調用拷貝構造)
七、靜態成員與靜態成員函數
- 1、類成員被static修飾後,就會儲存在bss段(此段是有編譯存放的而且大小固定),在程式中動態建立對象時它的靜態成員就無法建立,所有的類對象共用一個靜態成員
- 2、靜態成員只能在類中聲明不能在類中定義(必須在類外定義)
類型 類名::成員名;
- 3、靜態成員就是聲明在類中的全域變數,在任何位置都可以使用 類名::靜態變數名
- 4、靜態成員函數,類中的成員函數被static修飾後就變成了靜態成員函數,所有對象共用一份靜態成員函數
- 5、靜態成員函數不會傳遞this指標,也就不能訪問成員變數
不通過對象也能調用靜態成員函數
類名::靜態成員函數(參數)
八、單例模式
- 1、只能建立出一個對象的類,這種類叫做單例類,這種模式就叫做單例模式
- 2、為什麼需要單例模式,是為了提高安全性和穩定性的技巧。
只允許存在唯一對象執行個體
單例模式的商業應用:
網站計數器
日誌管理系統
串連池、線程池、記憶體池
- 3、擷取對象執行個體的專門方法
a、全域變數的定義不受控制,能防君子不能防小人
b、專門方法是類的一部分,"我是類型我做主",
藉助類禁止在外部建立對象,僅在類內部提供擷取對象的介面。
4、如何?單例模式
a、禁止在類外部建立執行個體,私人所有的建構函式 private
b、類自己維護其唯一執行個體,
靜態成員變數 static 類名 instance;
靜態成員指標 static 類名* instance;
c、提供訪問該執行個體的方法,靜態成員函數getInstance()
5、餓漢單例模式
不管是否需要對象都已經建立好了。
優點:效率高、速度快、穩定。
缺點:浪費資源,不管需不需要對象都已經建立好;
6、懶漢單例模式
當首次使用擷取對象時才會真正建立出對象。
優點:節約資源
缺點:效率低,速度慢,不安全(多線程情況下)。
九、操作符函數
在C++中,編譯器有能力把一個由資料、對象和操作符共同組成的運算式,解釋為對一個全域或成員函數的調用。 該全域或成員函數被稱為操作符函數,通過重定義操作符函數,可以實現針對自訂類型的運演算法則,並使之與內建類型一樣參與各種運算式。
十、雙目操作符運算式
- 成員函數
形如L#R雙目操作符運算式,將被編譯器解釋為 L.operator#(R)
a-b+c == a.operator-(b).operator+(c)
- 全域函數
形如L#R的雙目操作符運算式,將被編譯器解釋為 ::operator#(L,R)
a-(b+c) == ::operator-(a,::operator+(b,c))
十一、單目操作符運算式
- 成員函數
形如#O或O#的單目動作表達式,將被編譯器解釋為 O.operator#(),唯一的運算元是調用對象。
- 全域函數
形如#O或O#的單目動作表達式,將被編譯器解釋為 ::operator#(O),唯一的運算元是調用對象。
十二、典型的雙目運算子多載
成員函數 Point operator /+-*%|^& (Point& that) { Point t; // 會調用無參構造 t.x = x / that.x; t.y = y / that.y; return t; // 不能返回局部對象的引用,否則會出現懸Null 參考 } 注意:原對象的值不變,要產生一個臨時的對象 bool operator > < >= <= == != || && (Point& that) { } Point& operator += -= *= /= (Point& that) { return *this; } 注意:運算子的重載要符合情理。
全域函數
可能會訪問到參數的私人成員:
1、把成員變成公開,但會破壞類的封閉性。
2、把全域函式宣告為友元(友元不是成員),
3、不能在友元函數中直接存取成員變數。
Point operator + (Point& a,Point& b) { Point t(a.x+b.x,a.y+b.y); return t; }
十三、典型的單目運算子多載
成員函數: 前++/-- Point& operator ++/-- (void) { } 後++/-- Point operator ++/-- (int) { } 全域函數: 前++/-- Point& operator ++/-- (Point&) { } 後++/-- Point operator ++/-- (Point&,int) { }
十四、輸入、輸出運算子多載
輸入、輸出運算子不能重載為成員函數,只能是友元。 ostream& operator << (ostream& os,Point& p) { } istream& operator >> (istream& is,Point& p) { }
十五、特殊的運算子的重載
[] 下標運算子,可以把對象當作數組來使用。
() 函數運算子,可以把對象當作函數來使用。
-> 成員訪問運算子,可以把對象當作指標來使用。
解引用運算子,可以把對象當作指標來使用。
new/delete 也可以進行重載,但不建議使用。
new會自動調用重載的new函數再建構函式。
delete會先調用析構再調用重載的delete函數。
只有極個別的運算子的重載對於對象來說是有意義(>>,<<)
常考的運算子多載:前++/--,後++/--
十六、運算子多載的一些限制
- 1、不能重載的運算子
:: 範圍限定符
. 成員訪問運算
.* 成員指標解引用
?: 三目運算子
sizeof 位元組長度運算子
typeid 類型資訊操作符
- 2、運算子的重載改變不了運算子的優先順序
- 3、無法改變運算子的操作個數
- 4、無法發明新的運算子
- 5、重載運算子要注意運算子的一致性
不要改變運算子預設的運算規則
- 6、運算子的重載是為了方便使用、增強可讀,不應該成功賣弄的工具。
來自為知筆記(Wiz)
C++知識點小結 (二)