c++學習心得第二期 多型+檔案操作
c++學習心得第二期 多型+檔案操作
一、多型
1、多型的基本概念
多型是C++物件導向三大特性之一
多型分為兩類
靜態多型: 函式過載 和 運算子過載屬於靜態多型,複用函式名
動態多型: 派生類和虛擬函式實現執行時多型
靜態多型和動態多型區別:
靜態多型的函式地址早繫結 - 編譯階段確定函式地址
動態多型的函式地址晚繫結 - 執行階段確定函式地址
#include<iostream>
#include<string>
using namespace std;
//因為早繫結,所以地址已經是animal的地址了 想執行小貓說話但結果是動物說話
class Animal{
public:
void speak()
{
cout <<"動物在說話" << endl;
}
};
class Cat :public Animal{
public:
void speak()
{
cout <<"小貓在說話" << endl;
}
};
//執行說話函式
//地址早繫結 在編譯階段確定函式的地址。
void doSpeak(Animal &animal)
{
animal.speak();
}
void test01()
{
Cat cat;
doSpeak(cat);
}
int main()
{
test01();
system("pause");
return 0;
}
#include<iostream>
#include<string>
using namespace std;
class Animal{
//在函式前加 virtual 變成動態繫結。
public:
virtual void speak()
{
cout <<"動物在說話" << endl;
}
};
class Cat :public Animal{
public:
void speak()
{
cout <<"小貓在說話" << endl;
}
};
void doSpeak(Animal &animal)
{
animal.speak();
}
void test01()
{
Cat cat;
doSpeak(cat);
}
int main()
{
test01();
system("pause");
return 0;
}
多型滿足條件
有繼承關係
子類重寫父類中的虛擬函式
多型使用條件
父類指標或引用指向子類物件
重寫:函式返回值型別 函式名 引數列表 完全一致稱為重寫
2、多型案例一-計算器類
分別利用普通寫法和多型技術,設計實現兩個運算元進行運算的計算器類
多型的優點:
程式碼組織結構清晰
可讀性強
利於前期和後期的擴充套件以及維護
#include<iostream>
#include<string>
using namespace std;
class AbstractCalculator{
public :
virtual int result() = 0;
public:
int num1;
int num2;
};
class AddCalculator:public AbstractCalculator{
public:
AddCalculator(int num1,int num2)
{
this->num1 = num1;
this->num2 = num2;
}
int result()
{
return num1 + num2;
}
};
class SubstractorCalculator :public AbstractCalculator{
public:
SubstractorCalculator(int num1, int num2)
{
this->num1 = num1;
this->num2 = num2;
}
int result()
{
return num1 - num2;
}
};
class MultiplyrCalculator :public AbstractCalculator{
public:
MultiplyrCalculator(int num1, int num2)
{
this->num1 = num1;
this->num2 = num2;
}
int result()
{
return num1*num2;
}
};
void test01()
{
AbstractCalculator *abc = new AddCalculator(10, 10);
cout << abc->result() << endl;
delete abc;
abc = new SubstractorCalculator(20,10);
cout << abc->result() << endl;
delete abc;
abc = new MultiplyrCalculator(20, 10);
cout << abc->result() << endl;
delete abc;
}
int main()
{
test01();
system("pause");
return 0;
}
3、純虛擬函式和抽象類
在多型中,通常父類中虛擬函式的實現是毫無意義的,主要都是呼叫子類重寫的內容
因此可以將虛擬函式改為純虛擬函式
純虛擬函式語法:virtual 返回值型別 函式名 (引數列表)= 0 ;
當類中有了純虛擬函式,這個類也稱為抽象類
抽象類特點:
無法例項化物件
子類必須重寫抽象類中的純虛擬函式,否則也屬於抽象類
#include<iostream>
#include<string>
using namespace std;
//純虛擬函式
//類中只要有一個純虛擬函式就稱為抽象類
//抽象類無法例項化物件
//子類必須重寫父類中的純虛擬函式,否則也屬於抽象類
class Base{
public:
virtual void func() = 0;
};
class Son :public Base{
public:
void func()
{
cout <<"呼叫了 func函式" << endl;
}
};
void test01()
{
Base *base;
//設定了純虛擬函式即為抽象函式,因此抽象函式不能例項化
//base = new Base;
base = new Son();
base->func();
delete base;//分配到堆區的記憶體要刪除
}
int main()
{
test01();
system("pause");
return 0;
}
4、多型案例二-製作飲品
製作飲品的大致流程為:煮水 - 沖泡 - 倒入杯中 - 加入輔料
利用多型技術實現本案例,提供抽象製作飲品基類,提供子類製作咖啡和茶葉
#include<iostream>
#include<string>
using namespace std;
class AbstractDrinking
{
public:
virtual void Boil() = 0;
virtual void Brew() = 0;
virtual void PourInCup() = 0;
virtual void PusSomething() = 0;
void MakeDrink()
{
Boil();
Brew();
PourInCup();
PusSomething();
}
};
class Coffee :public AbstractDrinking
{
void Boil()
{
cout <<"礦泉水" << endl;
}
void Brew()
{
cout <<"泡" << endl;
}
void PourInCup()
{
cout <<"倒" << endl;
}
void PusSomething()
{
cout <<"加牛奶" << endl;
}
};
class Tea :public AbstractDrinking
{
void Boil()
{
cout << "自來水" << endl;
}
void Brew()
{
cout << "加熱" << endl;
}
void PourInCup()
{
cout << "潑" << endl;
}
void PusSomething()
{
cout << "加樹葉" << endl;
}
};
//使用引用呼叫虛擬函式和多型
void DoWork(AbstractDrinking& drinking)
{
drinking.MakeDrink();
}
//使用指標呼叫虛擬函式和多型
void DoWorkByPoint(AbstractDrinking *dringing)
{
dringing->MakeDrink();
}
void test01()
{
//使用引用呼叫虛擬函式和多型
Tea tea;
DoWork(tea);
Coffee coffee;
DoWork(coffee);
cout <<"------------------>" << endl;
//使用指標呼叫虛擬函式和多型
AbstractDrinking *drinking = new Tea;
DoWorkByPoint(drinking);
delete drinking;
drinking = new Coffee;
DoWorkByPoint(drinking);
delete drinking;
}
int main()
{
test01();
system("pause");
return 0;
}
5、虛析構和純虛析構
多型使用時,如果子類中有屬性開闢到堆區,那麼父類指標在釋放時無法呼叫到子類的析構程式碼
解決方式:將父類中的解構函式改為虛析構或者純虛析構
虛析構和純虛析構共性:
可以解決父類指標釋放子類物件
都需要有具體的函式實現
虛析構和純虛析構區別:
如果是純虛析構,該類屬於抽象類,無法例項化物件
虛析構語法:
virtual ~類名(){}
純虛析構語法:
virtual ~類名() = 0;
類名::~類名(){}
總結:
- 虛析構或純虛析構就是用來解決通過父類指標釋放子類物件
- 如果子類中沒有堆區資料,可以不寫為虛析構或純虛析構
- 擁有純虛解構函式的類也屬於抽象類
#include<iostream>
#include<string>
using namespace std;
class Animal{
public:
Animal()
{
cout <<"Animal 建構函式的呼叫" << endl;
}
~Animal()
{
cout <<"Animal 解構函式的呼叫" << endl;
}
virtual void speak() = 0;
};
class Cat :public Animal
{
public:
Cat()
{
cout <<"小貓的建構函式在呼叫" << endl;
}
~Cat()
{
cout <<"小貓的解構函式在呼叫" << endl;
}
void speak()
{
cout <<"小貓在叫" << endl;
}
};
void test01()
{
Animal* animal = new Cat;
animal->speak();
delete animal;
}
int main()
{
test01();
system("pause");
return 0;
}
小貓的解構函式沒有呼叫,如果小貓中存在堆區的分配,有開闢的記憶體空間沒有釋放會造成記憶體洩漏。因此要在父類中使用虛析構和純虛析構,可以是子類中的解構函式被呼叫。
#include<iostream>
#include<string>
using namespace std;
class Animal{
public:
Animal()
{
cout <<"Animal 建構函式的呼叫" << endl;
}
virtual ~Animal() = 0;
virtual void speak() = 0;
};
Animal:: ~Animal()
{
cout << "Animal 解構函式的呼叫" << endl;
}
class Cat :public Animal
{
public:
Cat(string name)
{
cout <<"小貓的建構函式在呼叫" << endl;
m_Name = new string(name);
}
~Cat()
{
if (m_Name != NULL)
{
delete m_Name;
m_Name = NULL;
}
cout <<"小貓的解構函式在呼叫" << endl;
}
void speak()
{
cout <<*m_Name<<"小貓在叫" << endl;
}
string *m_Name;
};
void test01()
{
Animal* animal = new Cat("Jack");
animal->speak();
delete animal;
}
int main()
{
test01();
system("pause");
return 0;
}
6、多型案例三-電腦組裝
電腦主要組成部件為 CPU(用於計算),顯示卡(用於顯示),記憶體條(用於儲存)
將每個零件封裝出抽象基類,並且提供不同的廠商生產不同的零件,例如Intel廠商和Lenovo廠商
建立電腦類提供讓電腦工作的函式,並且呼叫每個零件工作的介面
測試時組裝三臺不同的電腦進行工作
#include<iostream>
#include<string>
using namespace std;
//建立 cpu memory videocard 虛擬函式 建立Inter和Lenovo對虛擬函式進行實現。
//建立 computer 作為cpu memory 和 videocard的集合類 進行組裝
class Cpu{
public:
virtual void calculate() = 0;
};
class VideoCard
{
public:
virtual void display() = 0;
};
class Memory
{
public:
virtual void storage() = 0;
};
class Computer
{
public:
Computer(Cpu* c,Memory *m,VideoCard *v)
{
cpu = c;
memory = m;
videocard = v;
}
~Computer()
{
if (cpu != NULL)
{
delete cpu;
cpu = NULL;
}
if (memory != NULL)
{
delete cpu;
memory = NULL;
}
if (videocard != NULL)
{
delete cpu;
videocard = NULL;
}
}
void work()
{
cpu->calculate();
memory->storage();
videocard->display();
}
private:
Cpu *cpu;
Memory *memory;
VideoCard *videocard;
};
//具體廠商
//Intel廠商
class IntelCPU :public Cpu
{
public:
virtual void calculate()
{
cout << "Intel的CPU開始計算了!" << endl;
}
};
class IntelVideoCard :public VideoCard
{
public:
virtual void display()
{
cout << "Intel的顯示卡開始顯示了!" << endl;
}
};
class IntelMemory :public Memory
{
public:
virtual void storage()
{
cout << "Intel的記憶體條開始儲存了!" << endl;
}
};
//Lenovo廠商
class LenovoCPU :public Cpu
{
public:
virtual void calculate()
{
cout << "Lenovo的CPU開始計算了!" << endl;
}
};
class LenovoVideoCard :public VideoCard
{
public:
virtual void display()
{
cout << "Lenovo的顯示卡開始顯示了!" << endl;
}
};
class LenovoMemory :public Memory
{
public:
virtual void storage()
{
cout << "Lenovo的記憶體條開始儲存了!" << endl;
}
};
void test01()
{
//第一臺電腦零件
Cpu * intelCpu = new IntelCPU;
VideoCard * intelCard = new IntelVideoCard;
Memory * intelMem = new IntelMemory;
cout << "第一臺電腦開始工作:" << endl;
//建立第一臺電腦
Computer * computer1 = new Computer(intelCpu, intelMem, intelCard);
computer1->work();
delete computer1;
cout << "-----------------------" << endl;
cout << "第二臺電腦開始工作:" << endl;
//第二臺電腦組裝
Computer * computer2 = new Computer(new LenovoCPU, new LenovoMemory,new LenovoVideoCard);
computer2->work();
delete computer2;
cout << "-----------------------" << endl;
cout << "第三臺電腦開始工作:" << endl;
//第三臺電腦組裝
Computer * computer3 = new Computer(new LenovoCPU, new LenovoMemory, new LenovoVideoCard);
computer3->work();
delete computer3;
}
int main()
{
test01();
system("pause");
return 0;
}
二、檔案操作
程式執行時產生的資料都屬於臨時資料,程式一旦執行結束都會被釋放
通過檔案可以將資料持久化
C++中對檔案操作需要包含標頭檔案 < fstream >
檔案型別分為兩種:
文字檔案 - 檔案以文字的ASCII碼形式儲存在計算機中
二進位制檔案 - 檔案以文字的二進位制形式儲存在計算機中,使用者一般不能直接讀懂它們
操作檔案的三大類:
ofstream:寫操作
ifstream: 讀操作
fstream : 讀寫操作
1.文字寫檔案
寫檔案步驟如下:
包含標頭檔案
#include
建立流物件
ofstream ofs;
開啟檔案
ofs.open(“檔案路徑”,開啟方式);
寫資料
ofs << “寫入的資料”;
關閉檔案
ofs.close();
注意: 檔案開啟方式可以配合使用,利用|操作符
**例如:**用二進位制方式寫檔案 ios::binary | ios:: out
#include<iostream>
using namespace std;
#include<fstream>
void test01()
{
ofstream ofs;
ofs.open("text.txt",ios::out);
ofs << "姓名:張三" << endl;
ofs << "性別:男" << endl;
ofs.close();
}
int main()
{
test01();
system("pause");
return 0;
}
檔案操作必須包含標頭檔案 fstream
讀檔案可以利用 ofstream ,或者fstream類
開啟檔案時候需要指定操作檔案的路徑,以及開啟方式
利用<<可以向檔案中寫資料
操作完畢,要關閉檔案
2.文字讀檔案
讀檔案與寫檔案步驟相似,但是讀取方式相對於比較多
讀檔案步驟如下:
包含標頭檔案
#include
建立流物件
ifstream ifs;
開啟檔案並判斷檔案是否開啟成功
ifs.open(“檔案路徑”,開啟方式);
讀資料
四種方式讀取
關閉檔案
ifs.close();
#include<iostream>
using namespace std;
#include<fstream>
#include<string>
void test01()
{
ifstream ifs;
ifs.open("text.txt",ios::in);
if (!ifs.is_open())
{
cout <<"檔案開啟失敗" << endl;
return;
}
string buf;
while (getline(ifs,buf))
{
cout <<buf << endl;
}
}
int main()
{
test01();
system("pause");
return 0;
}
3、二進位制檔案
以二進位制的方式對檔案進行讀寫操作
開啟方式要指定為 ios::binary
4、二進位制寫檔案
二進位制方式寫檔案主要利用流物件呼叫成員函式write
函式原型 :ostream& write(const char * buffer,int len);
引數解釋:字元指標buffer指向記憶體中一段儲存空間。len是讀寫的位元組數
檔案輸出流物件 可以通過write函式,以二進位制方式寫資料
#include<iostream>
using namespace std;
#include<fstream>
#include<string>
class Person{
public:
char m_Name[64];
int m_Age;
};
//二進位制寫檔案
void test01()
{
//建立輸出流物件
ofstream ofs("person.txt",ios::out|ios::binary);
Person p = {"張三",18};
ofs.write((const char*)&p,sizeof(p));
ofs.close();
}
int main()
{
test01();
system("pause");
return 0;
}
5、二進位制讀檔案
二進位制方式讀檔案主要利用流物件呼叫成員函式read
函式原型:istream& read(char *buffer,int len);
引數解釋:字元指標buffer指向記憶體中一段儲存空間。len是讀寫的位元組數
檔案輸入流物件 可以通過read函式,以二進位制方式讀資料
#include<iostream>
using namespace std;
#include<fstream>
#include<string>
class Person{
public:
char m_Name[64];
int m_Age;
};
//二進位制寫檔案
void test01()
{
ifstream ifs("person.txt",ios::in|ios::binary);
if (!ifs.is_open())
{
cout <<"檔案開啟失敗" << endl;
}
Person p;
ifs.read((char*)&p,sizeof(p));
cout <<"姓名 " <<p.m_Name <<" 年齡 " <<p.m_Age<< endl;
}
int main()
{
test01();
system("pause");
return 0;
}
相關文章
- 深入理解 C++ 中的多型與檔案操作C++多型
- C語言檔案輸入和輸出操作的學習心得(一)C語言
- c++學習(1)--C++封裝、繼承、多型C++封裝繼承多型
- C++學習心得第二期 記憶體四區+new+引用+函式高階C++記憶體函式
- 學習心得:asp.net操作cookieASP.NETCookie
- Linux學習之檔案操作Linux
- C++寫檔案操作C++
- 開心檔之C++ 多型C++多型
- (十七)Python學習之檔案操作Python
- C++學習筆記----讀寫檔案C++筆記
- C++讀寫檔案操作C++
- C++檔案讀寫操作C++
- C++ 檔案操作詳解C++
- c++ IO類,檔案操作C++
- C++中的檔案操作C++
- Java學習-多型Java多型
- Python模組學習:zipfile zip檔案操作Python
- 學習心得
- vim學習筆記——多檔案、多視窗編輯筆記
- Golang 原始碼學習(一) —— os/file 檔案操作Golang原始碼
- python菜鳥教程學習13:檔案操作Python
- LINUX學習(一)檔案與目錄操作Linux
- Html5學習系列(四)檔案操作APIHTMLAPI
- C++ 一些學習筆記(十二)類和物件-多型C++筆記物件多型
- C++多型C++多型
- C++——多型C++多型
- 學習心得之華為數字化轉型框架框架
- 我的MYSQL學習心得(四)資料型別MySql資料型別
- 我的MYSQL學習心得(4) : 資料型別MySql資料型別
- Linux檔案型別(學習筆記六)Linux型別筆記
- C++多執行緒學習C++執行緒
- Redis 學習心得Redis
- Github學習心得Github
- Django學習心得Django
- git學習心得Git
- Lotus學習心得(-)
- php學習心得PHP
- Guice學習心得GUI