Part 1.梳理思維導圖
一.運算符重載
1.運算符重載的作用
使原本只能對基本數據類型生效的運算符,在重載后,滿足可以對構造類型數據生效。
2.關系運算符重載
? ? ? ? a.關系運算符種類
>???????? >= ????????< ????????<= ????????==???????? !=
? ? ? ? b.分析參數
表達式:左值 關系運算符 右值
左值:只能為左值
右值:可以為左值,也可以為右值
返回值:bool(ture or false)
? ? ? ? c.函數格式
成員函數:bool operator關系運算符(const 類名 &R) const
全局函數:bool operator關系運算符(const類名 &L,const 類名 &R)
? ? ? ? d.分析
因為返回值使bool類型,所以函數頭為bool;
operator關系運算符為函數名,由于成員函數的實現方式是左值調用函數參數為右值,所以參數只有右值;
由于不改變右值,所以該成員函數后面加上const,使其成為常成員函數;
全局函數中實現方式為一個函數調用左值和右值就行關系運算,所以參數為兩個,因為關系運算不改變參數值,所以加const
? ? ? ? e.例子
以關系運算符>為例,當需要全局函數實現時,需要在類內添加友元
#include <iostream>using namespace std;class num
{
// friend const num operator+(const num &L,const num &R);
// friend bool operator>(const num &L,const num &R);
private:int a;int b;
public:num(){}num(int a,int b):a(a),b(b){}const num operator+(const num &R) const{num temp;temp.a = a + R.a;temp.b = b + R.b;return temp;}//成員函數實現bool operator>(const num &R) const{if(a > R.a && b < R.b)return true;elsereturn false;}void show(){cout << "a = " << a << " b = " << b << endl;}
};//const num operator+(const num &L,const num &R)
//{
// num temp;
// temp.a = L.a + R.a;
// temp.b = L.b + R.b;
// return temp;
//}//全局函數實現,需要在類內添加友元
//bool operator>(const num &L,const num &R)
//{
// if(L.a > R.a && L.b < R.b)
// return true;
// else
// return false;
//}ostream & operator<<(ostream &cout,const num &n)
{cout << n.a << " " << n.b << endl;return cout;
}istream & operator>>(istream &cin,num &n)
{cin >> n.a >> n.b;return cin;
}int main()
{num n1(2,3);num n2(3,4);num n3 = n1+n2;n3.show();if(n1 > n2)cout << "n1 > n2" << endl;elsecout << "n1 < n2" << endl;return 0;
}
3.賦值運算符重載
? ? ? ? a.賦值運算符種類
+=? ? ? ? -=? ? ? ? *=? ? ? ? /=? ? ? ? %=
? ? ? ? b.分析參數
表達式:左值 賦值運算符 右值(a += b)
左值:只能為左值
右值:可以為左值,也可以為右值
返回值:自身的引用
? ? ? ? c.函數格式
成員函數:類名 &operator賦值運算符(const 類名 &R)
全局函數:類名 &operator賦值運算符(類名 &L,const 類名 &R)
? ? ? ? d.分析
因為成員函數和全局函數返回的均是左值的引用,所以函數的返回值類型為 類名 &;
成員函數實現方式時將右值作為參數給左值調用,所以只有右值為參數;
全局變量需要二者均為參數,但是由于右值會發生變化,所以只有左值加const;
? ? ? ? e.例子
#include <iostream>using namespace std;class num
{
// friend const num operator+(const num &L,const num &R);
// friend bool operator>(const num &L,const num &R);
// friend num & operator+=(num &L,const num &R);private:int a;int b;
public:num(){}num(int a,int b):a(a),b(b){}const num operator+(const num &R) const{num temp;temp.a = a + R.a;temp.b = b + R.b;return temp;}bool operator>(const num &R) const{if(a > R.a && b < R.b)return true;elsereturn false;}//成員函數實現num &operator+=(const num &R){a = a + R.a;b = b + R.b;return *this;}void show(){cout << "a = " << a << " b = " << b << endl;}
};//const num operator+(const num &L,const num &R)
//{
// num temp;
// temp.a = L.a + R.a;
// temp.b = L.b + R.b;
// return temp;
//}//bool operator>(const num &L,const num &R)
//{
// if(L.a > R.a && L.b < R.b)
// return true;
// else
// return false;
//}//全局函數實現
//num & operator+=(num &L,const num &R)
//{
// L.a = L.a + R.a;
// L.b = L.b + R.b;
// return L;
//}int main()
{num n1(2,3);num n2(3,4);num n3 = n1+n2;n3.show();// if(n1 > n2)
// cout << "n1 > n2" << endl;
// else
// cout << "n1 < n2" << endl;n1 += n2 += n3;n1.show();n2.show();n3.show();return 0;
}
4.自增自減運算符
? ? ? ? a.自增自減運算符種類
++(前自增和后自增)? ? ? ? --(前自減和后自減)
? ? ? ? b.分析參數
表達式:前:自增自減運算符 值(++a)? ? ? ? 后:值 自增自減運算符(a++)
值:只能為左值
返回值:前:自身的引用? ? ? ? 后:右值
? ? ? ? c.函數格式
成員函數:前:類名 &operator自增自減運算符()
? ? ? ? ? ? ? ? ? 后:const 類名 operator自增自減運算符(int )
全局函數:前:類名 &operator自增自減運算符(類名 &O)
? ? ? ? ? ? ? ? ? 后:const 類名 operator自增自減運算符(類名 &O,int)
? ? ? ? d.前自增和后自增的區別
前自增返回段值是一個左值,可以繼續被使用于函數,而后自增返回的是一個右值,不能被繼續適用于函數
????????e.分析
因為自增自減函數只需要調用自己,所以成員函數內沒參數,全局函數內參數為自己;
前自增函數和后自增函數都是一樣的引用,為了能滿足函數重載,使函數使用的更方便,在后自增函數中增加一個啞元,使其滿足函數重載的定義(參數個數不同或者參數類型不同);
前自增的返回值類型是類名 &(類的引用)是個左值,后自增返回的是類名(類的右值返回)是個右值;
? ? ? ? f.例子
因為后自增是返回沒自增前的值,所以需要定義一個新的臨時類成員,用于返回
#include <iostream>using namespace std;class num
{
// friend const num operator+(const num &L,const num &R);
// friend bool operator>(const num &L,const num &R);
// friend num & operator+=(num &L,const num &R);
// friend num &operator++(num &L);
// friend const num operator++(num &L,int);
private:int a;int b;
public:num(){}num(int a,int b):a(a),b(b){}const num operator+(const num &R) const{num temp;temp.a = a + R.a;temp.b = b + R.b;return temp;}bool operator>(const num &R) const{if(a > R.a && b < R.b)return true;elsereturn false;}num &operator+=(const num &R){a = a + R.a;b = b + R.b;return *this;}//成員函數實現前自增num &operator++(){a++;b++;return *this;}//成員函數實現后自增const num operator++(int){num temp;temp.a = a++;temp.b = b++;return temp;}void show(){cout << "a = " << a << " b = " << b << endl;}
};//const num operator+(const num &L,const num &R)
//{
// num temp;
// temp.a = L.a + R.a;
// temp.b = L.b + R.b;
// return temp;
//}//bool operator>(const num &L,const num &R)
//{
// if(L.a > R.a && L.b < R.b)
// return true;
// else
// return false;
//}//num & operator+=(num &L,const num &R)
//{
// L.a = L.a + R.a;
// L.b = L.b + R.b;
// return L;
//}//全局函數實現前自增
//num &operator++(num &L)
//{
// ++L.a;
// ++L.b;
// return L;
//}//全局函數實現后自增
//const num operator++(num &L,int)
//{
// num temp;
// temp.a = L.a++;
// temp.b = L.b++;
// return temp;
//}int main()
{num n1(2,3);num n2(3,4);num n3 = n1+n2;n3.show();// if(n1 > n2)
// cout << "n1 > n2" << endl;
// else
// cout << "n1 < n2" << endl;// n1 += n2 += n3;
// n1.show();
// n2.show();
// n3.show();cout << "++++++++++++++++++" << endl;n1.show();++n1;n1.show();cout << "++++++++++++++++++" << endl;n1.show();n2.show();n2 = n1++;n1.show();n2.show();return 0;
}
5.插入提取運算符重載
? ? ? ? a.插入提取運算符類型
<<插入運算符? ? ? ? >>提取運算符
? ? ? ? b.分析參數
表達式:左值 插入提取運算符 右值(cout << a)
左值:istream類的cin 或者 ostream類的cout
右值:類成員
返回值:iostram類的cin或者cout的引用
? ? ? ? c.函數格式
成員函數:因為返回值類型為iostram類,調用的函數為該類的函數,不適合在右值類內創建成員函數
全局函數:cout:ostream &operator<<(ostream &cout,const 類名 &a)
? ? ? ? ? ? ? ? ? cin:istream &operator>>(istream &cin,類名 &a)
? ? ? ? d.例子
#include <iostream>using namespace std;class num
{
// friend const num operator+(const num &L,const num &R);
// friend bool operator>(const num &L,const num &R);
// friend num & operator+=(num &L,const num &R);
// friend num &operator++(num &L);
// friend const num operator++(num &L,int);friend ostream & operator<<(ostream &cout,const num &n);friend istream & operator>>(istream &cin,num &n);
private:int a;int b;
public:num(){}num(int a,int b):a(a),b(b){}const num operator+(const num &R) const{num temp;temp.a = a + R.a;temp.b = b + R.b;return temp;}bool operator>(const num &R) const{if(a > R.a && b < R.b)return true;elsereturn false;}num &operator+=(const num &R){a = a + R.a;b = b + R.b;return *this;}num &operator++(){a++;b++;return *this;}const num operator++(int){num temp;temp.a = a++;temp.b = b++;return temp;}void show(){cout << "a = " << a << " b = " << b << endl;}
};//const num operator+(const num &L,const num &R)
//{
// num temp;
// temp.a = L.a + R.a;
// temp.b = L.b + R.b;
// return temp;
//}//bool operator>(const num &L,const num &R)
//{
// if(L.a > R.a && L.b < R.b)
// return true;
// else
// return false;
//}//num & operator+=(num &L,const num &R)
//{
// L.a = L.a + R.a;
// L.b = L.b + R.b;
// return L;
//}//num &operator++(num &L)
//{
// ++L.a;
// ++L.b;
// return L;
//}//const num operator++(num &L,int)
//{
// num temp;
// temp.a = L.a++;
// temp.b = L.b++;
// return temp;
//}//全局函數實現<<
ostream & operator<<(ostream &cout,const num &n)
{cout << n.a << " " << n.b << endl;return cout;
}//全局函數實現>>
istream & operator>>(istream &cin,num &n)
{cin >> n.a >> n.b;return cin;
}int main()
{num n1(2,3);num n2(3,4);num n3 = n1+n2;n3.show();// if(n1 > n2)
// cout << "n1 > n2" << endl;
// else
// cout << "n1 < n2" << endl;// n1 += n2 += n3;
// n1.show();
// n2.show();
// n3.show();cout << "++++++++++++++++++" << endl;n1.show();++n1;n1.show();cout << "++++++++++++++++++" << endl;n1.show();n2.show();n2 = n1++;n1.show();n2.show();return 0;
}
二.靜態成員
1.目的
申請靜態成員是讓每個類的這個靜態成員實現共享
2.注意事項
靜態成員不能在類內初始化,只能在類外初始化
靜態成員函數只能訪問靜態成員
3.格式
class 類名
{int a;static 數據類型 變量名; // 靜態數據成員static 返回值類型 函數名(形參列表)// 靜態成員函數{ }};數據類型 類名::變量名 = 初始化;
4.例子
該函數為模擬銀行存儲,balance為余額,rate為利率,靜態成員利率會在函數外改變,并使每一個賬戶成員利率一起改,靜態函數static double getrate()只能調用靜態成員rate,static double getmenory(Bankaccent &accent)靜態函數為了調用非靜態成員balance,只能調用類對象再調用
#include <iostream>using namespace std;class Bankaccent
{
private:double balance;static double rate;
public:Bankaccent(){}Bankaccent(double balance):balance(balance){};static double getrate(){return rate;}static void setrate(double setrate){rate = setrate;}static double getmenory(Bankaccent &accent){return accent.balance*(1+rate);}};double Bankaccent::rate = 0.05;int main()
{Bankaccent accent1(1000);cout << Bankaccent::getrate() << endl;Bankaccent::setrate(0.06);cout << Bankaccent::getrate() << endl;cout << Bankaccent::getmenory(accent1) << endl;return 0;
}
三.繼承
1.目的
1.實現代碼的復用性(重用性)
2.建立父類和子類之間的聯系
3.通過繼承 實現多態
2.繼承的概念
在已有的一個類基礎上,衍生出一個新的類,此為繼承
被繼承的類成為父類
繼承的類成為子類
子類擁有父類所有成員和成員函數
3.格式
class 類名 : 繼承方式 類名
{子類的拓展;
};
4.繼承方式
1.public:父類的成員繼承方式按原繼承方式保存。原父類中,public,protected類可以訪問private子類不能訪問
2.protected:父類的成員繼承方式按原繼承方式為public改為protected保存,其他繼承方式不變。原父類中,public,protected類可以訪問private子類不能訪問
3.private:父類的成員繼承方式全按private繼承方式保存。原父類中,public,protected類可以訪問private子類不能訪問
Part 2.程序
搭建一個貨幣的場景,創建一個名為 RMB 的類,該類具有整型私有成員變量 yuan(元)、jiao(角)和 fen(分),并且具有以下功能:
(1)重載算術運算符 + 和 -,使得可以對兩個 RMB 對象進行加法和減法運算,并返回一個新的 RMB 對象作為結果。
(2)重載關系運算符 >,判斷一個 RMB 對象是否大于另一個 RMB 對象,并返回 true 或 false。
(3)重載前置減減運算符 --,使得每次調用時 RMB 對象的 yuan、jiao 和 fen 分別減 1
(4)重載后置減減運算符 --,使得每次調用時 RMB 對象的 yuan、jiao 和 fen 分別減 1
(5)另外, RMB 類還包含一個靜態整型成員變量 count,用于記錄當前已創建的 RMB 對象的數量。每當創建一個新的 RMB 對象時,count 應該自增 1;每當銷毀一個 RMB 對象時,count 應該自減 1。
要求,需要在main 函數中測試上述RMB 類的功能
#include <iostream>using namespace std;class RMB
{
private:int yuan;int jiao;int fen;static int count;
public:RMB(){countplus();}RMB(int yuan,int jiao,int fen):yuan(yuan),jiao(jiao),fen(fen){countplus();}RMB(const RMB& other):yuan(other.yuan),jiao(other.jiao),fen(other.fen){countplus();}~RMB(){countdecrease();}const RMB operator+(const RMB &R){RMB temp;temp.yuan = yuan+R.yuan;temp.jiao = jiao+R.jiao;temp.fen = fen+R.fen;return temp;}const RMB operator-(const RMB &R){RMB temp;temp.yuan = yuan-R.yuan;temp.jiao = jiao-R.jiao;temp.fen = fen-R.fen;return temp;}bool operator>(const RMB &R){if(yuan > R.yuan)return true;elsereturn false;}RMB &operator--(){--yuan;--jiao;--fen;return *this;}const RMB operator--(int){RMB temp;temp.yuan = yuan--;temp.jiao = jiao--;temp.fen = fen--;return temp;}static void countplus(){count++;}static void countdecrease(){count--;}static int countshow(){return count;}void show(){cout << yuan << " " << jiao << " " << fen << endl;}
};int RMB::count = 0;int main()
{{cout << RMB::countshow() << endl;RMB r1(100,99,88);cout << RMB::countshow() << endl;RMB r2(55,101,76);cout << RMB::countshow() << endl;cout << "算數運算符+" << endl;r1 = r1+r2;r1.show();cout << "算數運算符-" << endl;r1 = r1-r2;r1.show();cout << "關系運算符>" << endl;bool a = r1 > r2;cout << a << endl;cout << "前自減運算符--" << endl;--r1;r1.show();cout << "后自減運算符--" << endl;RMB r3 = r2--;r3.show();r2.show();}cout << RMB::countshow() << endl;return 0;
}