一、多态、繼承
1、C++允許父子之間的類型轉換,不需要作強制類型轉換,父類的引用或指針可以直接指向子類對象;
2、位址早綁定:在編譯階段确定函數位址
3、位址晚綁定:在程式運作階段确定函數位址。
4、動态多态滿足條件:
- 有繼承關系
- 子類重寫父類中的虛函數
- 父類的指針或引用指向子類對象
5、多态原理
由于類中定義了虛函數,類的結構發生改變,類中會儲存一個虛函數指針(vfptr)指向虛函數表,虛函數表用來存放虛函數位址。
當子類繼承父類,沒重寫父類虛函數之前,除了繼承父類虛函數之外,還會繼承父類的虛函數指針,虛函數指針指向的虛函數表,存放的是父類虛函數位址。
當子類重寫父類虛函數之後子類中的虛函數表内部會把父類虛函數位址替換成子類的虛函數位址。
//父類的指針或引用指向子類對象
Animal &animal = cat;
animal.speak();
當調用時,傳的是哪個對象,就調用哪個對象虛函數表中的虛函數。
6、檢視類内部結構:打開vs2015開發人員指令提示工具,cd到類所在檔案夾,dir打開目錄之後輸入指令:d1 reportSingleClassLayou類名稱“檔案名”,即可檢視。
7、類成員函數為純虛函數的類稱為抽象類,抽象類特點:
- 無法執行個體化對象,無論是堆區還是棧區。
- 子類必須重寫抽象類中的純虛函數,否則也屬于抽象類。
8、虛析構和純虛析構
問題描述:多态使用時,父類指針或引用指向子類對象,父類指針或引用在釋放時無法調用到子類的析構代碼。如果子類中有屬性在堆區開辟記憶體,那麼将會造成記憶體洩漏。
解決:将父類中的析構函數改為虛析構或純虛析構。
虛析構和純虛析構共性:
- 可以解決父類指針釋放子類對象
- 都需要有具體的函數實作
虛析構和純虛析構差別:
- 如果是純虛析構,該類屬于抽象類,無法執行個體化對象。
二、檔案操作
C++中對檔案操作需要包含頭檔案fstream
檔案類型:
- 文本檔案:檔案以文本的ASCLL碼形式存儲在計算機中
- 二進制檔案:檔案以二進制的形式存儲在計算機中。
操作檔案三大類:
- ofstream:寫操作
- ifstream:讀操作
- fstream:讀寫操作
2.1、文本檔案
2.11、寫檔案
寫檔案步驟:
- 包含頭檔案:
#include <fstream>
- 建立流對象:
ofstream ofs;
- 打開檔案并判斷檔案是否打開成功:
ofs.open("檔案路徑",打開方式);
- 寫資料:
ofs<<"寫入的資料";
- 關閉檔案:
ofs.close();
讀檔案步驟:
- 包含頭檔案:
#include <fstream>
- 建立流對象:
ifstream ifs;
- 打開檔案并判斷檔案是否打開成功:
ifs.open("檔案路徑",打開方式);
- 讀資料,四種方式讀取:
//1、一行一行讀取
char buf[1024] = {0};
while(ifs>>buf);
//2、一行一行讀取
char buf[1024] = {0};
while(ifs.getline(buf,sizeof(buf)));
//3利用全局函數getline
#include <string>
string buf;
while(getline(ifs,buf));
//4、一個字元一個字元讀,直到檔案尾
char c;
while((c = ifs.get()) != EOF);
- 關閉檔案:
ofs.close();
二進制檔案-寫檔案:
二進制方式寫檔案主要利用流對象調用成員函數write
函數原型:
ostream& write(const char *buffer,int len);
函數解釋:字元指針buffer指向記憶體中的一段存儲空間,len是讀寫的位元組數
class Person
{
public:
char name[64];
int age;
};
int main()
{
//建立流對象
ofstream ofs("test.txt", ios::out | ios::binary);
//打開檔案
//ofs.open("test.txt", ios::out | ios::binary);
//判斷
if (!ofs.is_open())
{
cout << "檔案打開失敗!" << endl;
return;
}
//寫檔案
Person p = { "張三",18 };
ofs.write((const char *)&p, sizeof(Person));
//關閉檔案
ofs.close();
system("PAUSE");
return 0;
}
二進制檔案-讀檔案:
二進制方式寫檔案主要利用流對象調用成員函數read
函數原型:
ostream& read(char *buffer,int len);
函數解釋:字元指針buffer指向記憶體中的一段存儲空間,len是讀寫的位元組數
class Person
{
public:
char name[64];
int age;
};
int main()
{
//建立流對象并設定檔案打開方式
ifstream ifs("test.txt", ios::in | ios::binary);
//打開檔案
//ifs.open("test.txt", ios::out | ios::binary);
if (!ifs.is_open())
{
cout << "檔案打開失敗!" << endl;
return;
}
//讀取檔案
Person p;
ifs.read((char *)&p, sizeof(Person));
cout <<"姓名:"<< p.name <<",年齡:"<< p.age << endl;
ifs.close();
system("PAUSE");
return 0;
}
檔案打開方式:
打開方式 | 解釋 |
---|---|
ios::in | 為讀檔案而打開檔案 |
ios::out | 為寫檔案而打開檔案,檔案不存在則建立 |
ios:: ate | 初始位置:檔案尾 |
ios::app | 追加方式寫檔案 |
ios::trunc | 如果檔案存在先删除再建立 |
ios::binary | 二進制方式 |
注意:檔案打開方式可以配合使用,利用|操作符
例如:使用二進制方式寫檔案而打開檔案:
ios::binary | ios::out