一、面向對象程式設計
面向過程程式設計:關注于解決問題的方法、步驟。
面向對象程式設計:關注于誰能解決問題(類),以及解決問題需要的資料(成員變量),以及解決問題需要的技能(成員函數)。
抽象:想象出一個能解決問題的對象(觀察、想象),分析出解決問題需要的屬性(成員變量)和行為(成員函數)。
封裝:把抽象的結果分裝成類(資料類型),并設定上相應的通路權限。
使用封裝的類執行個體化對象,調用對象的成員函數與成員變量互相作用達到解決問題的目的。
繼承:在解決問題之前,先尋找有沒有能解決部分問題的類,如果有則把舊的類繼承并再拓展,然後縮短解決問題的時間、降低解決問題的難度。
多态:對象的多種形态,當對象發出一條指令,對象會根據自身的情況作出獨特的響應。
二、類和對象
1、把抽象結果封裝成一個資料類型(結構、類)
2、類就是一種資料類型
簡單類型:隻能表示一個變量,C/C++内建資料類型
數組類型:類型相同的多個變量
結構類型:不同類型的多個變量
類類型:不同類型的多個變量、函數
3、對象:類這種資料類型建立出來的執行個體,相當于結構變量
三、類的定義與執行個體化
1、類的一般形式
class 類名:繼承方式 父類名
{
通路限定符:
成員變量;
通路限定符:
//構造函數
類名(形參清單)
{
函數體;
}
//成員函數;
傳回值 函數名(形參清單)
{
函數體;
return val;
}
};
2、通路限定符
public:共有成員,可以在任何位置通路。
protected:受保護成員,隻能在自己的成員函數中和子類的成員函數中通路。
private:私有成員,隻能在自己的成員函數通路。
注意:在class中成員的預設是private,在struct中成員預設是public。
一般把成員變量設定為private,把成員函數設定為public。
3、對象的建立方法
在棧上建立方法
類名 對象;
類名 對象數組名[對象數量];
在堆上建立
類名* 對象指針 = new 類名;
類名* 對象指針 = new 類名[對象數量];
四、構造函數與初始化清單
1、什麼是構造函數
對象建立時自動調用的函數叫構造函數,負責完成一些準備工作。
2、無參構造
一個類中至少要有一個構造函數,如果不顯示實作,編譯器則自動生成一個沒有參數的構造函數,也叫無參構造。
如果顯式實作了構造函數,則無參構造不再生成,為了避免出錯,最好在顯式實作一個什麼都不做的無參構造。
3、有參構造
建立對象可以附帶一些資料給構造函數,用于初始化成員變量,這樣就必須顯式實作帶參數的構造函數,構造函數的參數就是建立對象時傳遞的資料。
注意:可以給有參構造設定預設參數,這樣可以達到無參構造的效果。
類名 對象(實參);
類名* 對象指針 = new 類名(實參);
4、單參構造
如果構造函數隻有一個,如此參數的類型與類型之間有類型提升的特性。
如果不想有類型提升的功能,可以在單參構造前加explicit關鍵字,禁止單參構造的類型提升。
class Test
{
public:
Test(int n)
{
}
};
Test t = 10;//自動調用單參構造而不會出錯。
5、初始化清單
構造函數(參數):成員1(參數1),成員2(參數2)//初始化清單
{
}
初始化清單就是一種給類的成員變量初始化的一種文法格式。
特點:
1、可以區分相同的參數和成員變量。
2、可以給類類型的成員變量或構造函數傳遞參數。
3、還可以給父類的構造函數傳遞參數
4、常屬性的成員隻能在初始化清單中指派
五、對象建立過程
- 配置設定類對象所需要的記憶體空間,無論棧或堆
- 傳遞實參調用構造函數,完成如下任務:
- 執行初始化清單
- 根據繼承表繼承順序調用父類構造函數
- 根據成員變量的定義順序調用成員變量的構造函數
- 執行構造函數中的代碼
六、類的聲明與實作分開
1、在頭檔案中聲明類
class 類名:繼承方式 父類
{
成員變量;
...
public:
類名(形參清單);
傳回值 成員函數(形參清單);
...
}
2、在源檔案中實作類的成員函數
#include "聲明類的頭檔案"
類名::類名(形參清單)
{
}
傳回值 類名::成員函數(形參清單)
{
函數體;
return val;
}
3、使用類隻需要包含類的頭檔案,然後使用者與類的源檔案目标檔案一起合并即可。
注意:如果類中的内容不多,在頭檔案中全部實作。
六、析構函數
1、什麼是析構函數
與構造函數一樣也是一種特殊的成員函數,它會在對象釋放的時候自動調用,負責一些收尾工作,如:儲存資料、釋放資源等。
2、函數格式
~類名(void)
{
}
3、析構函數的任務
負責釋放在構造函數中擷取到的所有資源。
執行過程:
1、先執行析構函數本身代碼
2、調用成員變量的析構函數
3、調用父類的析構函數
- 注意:析構函數與構造函數的執行順序剛好相反
#include <iostream>
using namespace std;
class Test
{
public:
Test(void)
{
cout<<"我是構造函數"<<endl;
}
~Test(void)
{
cout<<"我是析構函數"<<endl;
}
};
void func(void)
{
Test* t = new Test;
cout<<"-------"<<endl;
delete t;
}
int main(int argc,const char* argv[])
{
int n=3;
while(n--)
func();
}
六、預設的析構函數,構造函數
1、 定義
在設計一個類時,如果沒有顯示實作構造函數與析構函數,編譯器 會自動生成它們,也叫預設的構造和析構函數。
但生成的并不是真正文法意義上的函數,而是功能意義上的函數。
編譯器做為可執行指令的生成着,它有能力直接生成某些功能的二進制指令,不需要借助語言上的函數完成某些任務。
2、 什麼時候需要顯示實作構造函數
- 有成員需要初始化
- 需要一些參數做一些準備工作
- 需要在對象使用之前準備一些資源.如:申請一些堆記憶體
3.、什麼時候需要顯示實作析構函數
預設的析構函數會自動釋放編譯器能看得到的所有資源。如:成員變量,類成員,父類
- 儲存一些資料
- 成員變量中有指針,且指向堆記憶體。