頭檔案與類聲明
頭檔案中的防衛式聲明
#ifndef _FILENAME_
#define _FILENAME_
//...
#endif
擴充:為什麼要添加防衛式聲明(防止由于同一個頭檔案被包含多次,而導緻了重複定義。)
https://www.cnblogs.com/xyq10612/p/5910933.html頭檔案的布局
#ifndef __COMPLEX__
#define __COMPLEX__
#include<cmath>
//前置聲明
class ostream;
class complex;
complex&
_doapl(complex * ths, const complex);
//類聲明
class complex {
};
//類定義
complex::function....
#endif
模闆簡介
構造函數
内聯函數
1、你的函數在你的類本體裡面定義,那麼你就是一個inline。
2、如果你的函數太複雜,就沒有辦法inline
3、即使你把函數寫在了class裡面,最後的結果是否inline,是由編譯器去決定的。
4、不在類裡面定義的函數,你也可以把他inline,如上圖(2-2)。寫了一句:inline double
通路界别(access level)
1、什麼東西應該是private的呢? 應該是資料的部分,因為我們的資料應該是封裝起來的,不要被外界任意看到。
2、public 和private是可以交錯出現的。也就是說,你的class body很大,你可以先些一段public,之後寫一段private,後面想到了什麼,可以再插一段public,之後還可以在寫private
構造函數(constructor)
1、如果你想要建立一個對象,有一個函數會被自動的調用起來,這個函數就是構造函數。
2、下圖用動态的方法去建立一個對象,得到的會是一個指針。
3、構造函數的函數名和類名相同
4、他可以有參數,參數可以有預設值(default argument)
【有了預設值,當你建立對象的時候,如果沒有指明參數值,則用預設值】
5、他沒有傳回值類型
6、初值列——隻有構造函數享有這個功能
上圖把r設到re中去,把i設定到im中去
7、不寫初始列就不是練家子的原因:一個變量,它的數值的設定有兩個階段,一個是初始化,一個是指派。如果你不寫初始列,直接在函數體裡面指派,證明你放棄了初始化的階段,這樣的話指派的時間點會晚一些,效率會差一些。
8、你不可能在你的程式裡面去調用構造函數,你隻可能去建立對象。建立對象時,構造函數會自然而然被調用起來。
9、不帶指針的類,大部分不用寫析構函數。
構造函數可以有很多個-----重載(overloading)
兩個構造函數real的名稱相同,但是編譯器是可以厘清誰是誰的,是以可以重載。(編譯器通過函數名,裡面的參數名,參數類型等一系列的資訊來區分同名的構造函數)
1、在c++中,同名(其實對于編譯器來說是不同名的)的函數可以存在。
2、函數重載常常發生在構造函數中。
3、由于目前擁有的構造函數已經有預設值了,你還是可以去重載寫出其他的構造函數,但是你新寫的構造函數沒有預設值就不行,會引起沖突。如下圖,2就不會被調用
參數傳遞與傳回值
把構造函數(ctors)放在private區域裡
當不允許被外界建立對象的時候,把構造函數放在private裡面。那這個類有什麼用?
下圖是一個有名的設計模式singleton就用到了把ctors放在prvate裡
擴充:懶漢模式he餓漢模式
https://blog.csdn.net/hj605635529/article/details/70172842常量成員函數(在函數()的後面{}的前面,寫一個const )
該函數的意思是不會改變傳入的資料的内容,如下圖:
上述類中,如果函數real 和函數imag沒有加上const,則使用者希望不改變傳入值時,給自己的調用前面加上了const程式會報錯,因為類中的函數沒加上const代表你傳入的值可以改變。
是以,類中的real函數和imag函數需要加上const。此例說明,在設計函數的時候,要充分考慮各種情況。
const出現在對象或者變量的前面,說明我的對象或者變量是不可改動的。e.g
參數傳遞:pass by value vs pass by reference
1、Pass by value 是把資料整包的傳過去,壓入到棧中,是以盡量不要pass by value
2、引用在底層就相當于一個指針,是以傳遞引用就相當于傳遞指針那麼的快
3、傳引用 to const 可以保證傳遞速度快,而且你不會改變我傳入的值。如下圖:
傳回值傳遞:return by value vs return by reference
friend友元
可以直接拿你private的資料
同一個class内的各個對象互為友元(friend)
直接擷取了私有資料
對于類,老師會特别注意什麼地方呢?
1、資料放在private裡面
2、參數和傳回值盡可能使用reference來傳
3、類中的函數,應該加const的就要加,否則使用者在使用的時候會報錯。
4、構造函數的初始列要盡量去用。
什麼情況下不能return by reference
函數運作結束的時候,函數内建立的變量會被銷毀。如下圖,就不能return 參數三的reference
操作符重載與臨時對象
操作符重載-1,成員函數,this
1、在C++中,操作符就是一種函數,是可以讓你重新定義的。
2、所有的成員函數一定帶着一個隐藏的參數this,誰調用我的成員函數,這個隐藏的this就指向它(比如下圖中的this)
return by reference 文法分析
- 如果用reference來傳的話,傳遞者無需知道接受者是以什麼形式接收(也許是by value,也許是by reference)
(操作符要考慮使用者的連串使用情況
)
全域函數(不是在class中聲明的函數,如下圖所示)
操作符重載-2 非成員函數 無this
temp object臨時對象 typename ();(例如. int ();)
因為complex是函數中建立出來的,是以你的傳回值不是by reference,而是by value。
臨時對象:臨時想要的東西,我不想給你名稱,他的生命到下一行就結束了。
編譯器如何區分加減和取正負呢? ---看參數就知道了,隻有一個參數的,肯定是取正負
操作符重載 非成員函數
“<<” out put operator 不要想把這種操作符寫成一個成員函數
(操作符有兩種寫法,一種是成員函數的寫法,一種是非成員函數的寫法),這個操作符隻能考慮全局的那種寫法
因為如果你傳回的是引用,那麼你就是要把傳回值指派給”<<”左邊的”cout”,可是”cout”是标準庫的東西,你不可能指派給他,是以,對于”<<”操作符,無法寫成成員函數,其他的操作符寫成成員函數或者非成員函數都是可以的,但是單單這個不行。
函數的傳回值類型沒有用void,是因為有可能使用者會使用連續的輸出,如下圖