C++面向對象筆記(6):模板篇

C++模板篇

本章主要的內容:

  1. 友元函數、友元類
  2. 靜態數據成員、靜態成員函數
  3. 運算符重載
  4. 模板函數+模板類==》標準模板類
  5. 標準模板庫中向量Vector、鏈表list、映射map的使用

**注意:**關於友元,友元只是封裝的補充,會破壞封裝性,有定向暴露性(在實在沒有辦法的情況下使用友元)

1.友元函數-全局友元函數和友元成員函數

1.全局友元函數的定義和調用

class Time {
	// Time類的全局友元函數
    friend void printTime(Time &t);
    
public:
    Time(int hour, int min, int sec) {
        m_iHour = hour;
    	m_iMinute = min;
    	m_iSecond = sec;
    }
private:
    m_iHour = hour;
    m_iMinute = min;
    m_iSecond = sec;
};

// Time類的全局友元函數
void printTime(Time &t){
    cout << t.m_iHour << ":" 
        << t.m_iMinute << ":"  
        << t.m_iSecond << endl;
}

int main() {
    Time t(6,34,25);
    printTime(t);// 調用全局友元函數
    return 0;
}
/*輸出:
6:34:25
*/

2.友元成員函數的定義和調用

  1. Match類-Match.h:
//#include "Time.h"

// 先聲明有Time,代表之後會進行實現,但是不能使用include,會導致循環包含
class Time;

class Match {
public:
    void printTime(Time &t);
};

2.Match類-Match.cpp:

#include <iostream>
#include "Match.h"
#include "Time.h"// [!]不明白此處爲何可以include,不會造成Match和Time的循環包含嗎?

using namespace std;

void Match::printTime(Time &t) {
    cout << t.m_iHour << ":"
    << t.m_iMinute << ":"
    << t.m_iSecond << endl;
}

3.Time類-Time.h:

#include <iostream>
#include "Match.h"

using namespace std;

class Time {

    // 在這裏聲明友元函數,在此並不受本類的訪問限定符限定,
    // 故寫在public或private下並沒有區別
    friend void Match::printTime(Time &t);

public:
    Time(int hour,int min,int sec);

private:
    int m_iHour;
    int m_iMinute;
    int m_iSecond;
};

4.Time類-Time.cpp:

#include "Time.h"

Time::Time(int hour, int min, int sec) {
    m_iHour = hour;
    m_iMinute = min;
    m_iSecond = sec;
}

5.main.cpp:

#include <iostream>
#include "Time.c"

int main() {
    Time t(6,34,25);
    Match m;
    m.printTime(t);// 調用友元函數
    
    return 0;
}
/*輸出:
6:34:25
*/

2.友元類

友元類的寫法:

由於編譯器不同,友元類有兩種寫法:1、friend class 類名; 2、friend 類名

友元類的聲明與使用舉例

#include <iostream>
using namespace std;

// 事先加入Watch聲明,代表當前沒有實現,但是之後會進行實現
class Watch;

/**
 * 定義Time類
 * 數據成員:m_iHour, m_iMinute,m_iSecond 
 * 成員函數:構造函數
 * 友元類:Watch
 */
class Time{
    
    // 聲明Time類是Match類的友元類,即聲明Match有個友元類是Time
    // 所以Match就可以訪問Time中的成員了
    friend class Watch;
    
public:
	Time(int hour, int min, int sec){
		m_iHour = hour;
		m_iMinute = min;
		m_iSecond = sec;
	}
public:
	int m_iHour;
	int m_iMinute;
	int m_iSecond;
};

/**
 * 定義Watch類
 * 數據成員:m_tTime
 * 成員函數:構造函數
 * display用於顯示時間
 */
class Watch{
public:
	Watch(Time &timeObj) : m_tTime(timeObj){
	}
	void display(){
		cout << m_tTime.m_iHour << endl;
		cout << m_tTime.m_iMinute << endl;
		cout << m_tTime.m_iSecond << endl;
	}
public:
	Time m_tTime;
};


int main(){
	Time t(6, 30, 20);
	Watch w(t);
	w.display();

	return 0;
}

3.友元的總結

注意:

  1. 友元關係不可傳遞
  2. 友元關係得單向性(A是B的友元,不代表B是A的友元)
  3. 友元聲明的形式及數量不受限制
  4. 友元只是封裝的補充,會破壞封裝性,有定向暴露性(在實在沒有辦法的情況下使用友元)
  5. 友元的聲明不受訪問限定符影響,可以聲明在類中的任何位置。(即用friend修飾的聲明,僅限被friend修飾的這一句話不受)

對於友元關係的記法

  1. 友元函數:friend在哪個類出現,則此函數就是這個類的朋友,這個函數就可以對這個類的所有數據成員進行訪問了。(通過傳入的對象的引用來進行訪問)
  2. 友元類:friend在A類出現,則被friend修飾的B類就是這個類(A類)的朋友,所以B類就可以對A類中的所有數據成員進行訪問了(直接通過B類進行調用即可,無需使用引用)。即在A類中出現friend修飾的B,那麼B就是當前類的朋友,可以訪問當前類。

4.靜態變量與靜態函數

靜態成員依託於類,而不是對象,就算類沒有實例化對象,靜態成員也會存在於內存中。

假如有個類A,其中有靜態變量cout,在實例化a,b,c,d之前,cout這個靜態變量就已經存在於內存中 了。

靜態變量:

聲明:static int 變量名;

初始化(方法1):static int 變量名 = xxxx;(在類中聲明+初始化)

初始化(方法2):int 類名::變量名 = xxxx;(在類外初始化)

訪問(方法1):類名::變量名

訪問(方法2):對象名.變量名指針名->變量名

靜態函數:

初始化(方法1):static int 函數名(){xxxx;}(在類中初始化)

訪問(方法1):類名::函數名()

訪問(方法2):對象名.函數名()指針名->函數名()

int 類名::變量名 = xxxx

注意事項

  1. 靜態數據成員必須單獨初始化。(在對象實例化之前就有了,所以不能寫到類的構造函數中去)
  2. 靜態成員函數不能調用非靜態成員函數和費靜態數據成員。
  3. 靜態數據成員只有一份,且不依賴對象而存在。

對於上面注意事項的第2點做一下原理補充:

在類中的普通成員函數中調用普通成員變量,實際上爲了辨認出當前使用的變量屬於哪個對象,都會自動添加this指針;如果是靜態變量,因爲不依託於對象,而是依託於類,所以不會自動添加this指針,如下所示:

void FunctionName(){
    variable1 = "01";	// 普通成員變量
    variable2 = "02";	// 靜態成員變量
}
// 實際上會變成下面的這種形式
void FunctionName(ClassName *this){
    this->variable1 = "01";		// 會自動添加this指針
    variable2 = "02";			// 不會有this指針
}

靜態成員函數中,因爲這個函數不依託於對象,所以也不會有代表當前對象的this指針,所以如果使用普通成員變量,會不知道到底是哪個對象的成員變量,所以如果這樣調用會報錯,如下所示:

static int FunctionName(){
    // variable1是普通成員變量,variable2是靜態成員變量
    variable1 = "01";	// 會報錯!
    variable2 = "02";	//
}

但是普通的成員函數中使用靜態的數據成員,則是完全沒有問題。

靜態成員函數和const常量修飾符:

禁止在靜態函數後面加const,因爲const的本質是實際是對隱藏的this指針加const,因爲靜態函數根本不存在this指針,所以會報錯。

小總結

  1. 定義靜態成員函數和靜態數據成員都需要static關鍵字。

  2. 公有靜態成員函數可以被類直接調用。

  3. 靜態成員函數 既可以 訪問非靜態數據成員和靜態數據成員,也可以調用非靜態成員函數和靜態成員函數靜態成員函數只能訪問靜態數據成員和調用靜態成員函數

  4. 靜態數據成員不能在構造函數初始化,必須單獨初始化。

5.一元運算符的重載

**運算符重載:**給原有運算符賦予新的功能。

**運算符重載的本質:**函數重載。

關鍵字:operator

-(負號)的重載,有兩種重載的方法:

  1. 成員函數重載
  2. 友元函數重載

1.負號的重載-成員函數重載:

// 聲明
class Coordinate{
public:
    Coordinate(int x,int y);
    
    // 成員函數實現負號重載,
    // 返回類型是Coordinate&,關鍵字是operator,
    // 函數名是-,無參數
    Coordinate& operator-();
    
private:
    int m_iX;
    int m_iY;
}

// 實現
Coordinate& Coordinate::operator-(){
    
    // 兩種寫法都可以,this指針可加可不加
    this->m_iX = -(this->m_iX);
    this->m_iY = -(this->m_iY);
    //m_iX = -m_iX;
    //m_iY = -m_iY;
    
    // 【爲什麼是*this?】
    // 這裏我們的返回值是Coordinate對象的引用,這個引用該指向的是一個對象
    // 而this指針指向這個對象,所以我們要對this指針取值,從而獲取到對象
    // 也就是使用“*this”
    return *this;
}

// 調用
int main(){
    Coordinate coor1(3,5);
    -coor1;		// 相當於coor1.operator-();
    return 0;
}

2.負號的重載-友元函數重載:

// 聲明
class Coordinate{
    
    // 利用友元函數實現負號重載,
    // 友元函數也需要一個像成員函數自帶的this一樣的參數,
    // 故這裏表現爲Coordinate對象類型的參數,或引用
    // 即“Coordinate c”或“Coordinate &c”
    friend Coordinate& operator-(Coordinate& coor);
   
public:
    Coordinate(int x,int y);
private:
    int m_iX;
    int m_iY;
};

// 實現
// 注意:友元函數不屬於Coordinate類,所以不能寫成Coordinate::XXXX
Coordinate& operator-(){
    coor.m_iX = -coor.m_iX;
    coor.m_iY = -coor.m_iY;
    return *this;
}

// 調用
int main(){
    Coordinate coor1(3,5);
    -coor1;		// 相當於coor1.operator-();coor1這個對象會通過形參被傳入
    return 0;
}

++符號(前置)的重載:

前置++:先++,再使用

// 聲明
class Coordinate{
public:
    Coordinate(int x,int y);
    Coordinate& operator++(); // 前置++,返回當前對象的引用
private:
    int m_iX;
    int m_iY;
};

// 定義
Coordinate& Coordinate::operator++(){
    m_iX++;
    m_iY++;
    return *this;
}

// 調用
int main(){
    Coordinate coor1(3,5);
    ++coor1;		// coor1.operator++();
    return 0;
}

++符號(後置)的重載:

後置++:先使用,後++

// 聲明
class Coordinate{
public:
    Coordinate(int x,int y);
    
    // 成員函數實現++(後置)重載,後面的int是一個標誌,
    // int標誌代表後置重載,沒有爲什麼
    // 返回值也不再返回對象引用,而是返回一個對象
    Coordinate operator++(int); 
    
private:
    int m_iX;
    int m_iY;
};

// 實現
// 注意:這裏的int代表後置,是個標誌,不需要進行傳值,之後也不會使用
Coordinate operator++(int){		
    
    // 將當前對象保存在臨時對象中,這裏會調用拷貝構造函數,
    // 作爲返回,因爲++後置是先使用,再++
    Coordinate old(*this);
    
    // 將當前對象中的屬性進行++,如果之後再次調用此對象,就是++之後的值
    m_iX++;
    m_iY++;
    
    // 返回++之前的值
    return old;
}

// 調用
int main(){
    
    Coordinate coor1(3,5);
    coor1++; // coor1.operator++(0);系統會默認傳入一個值到標誌中,一般是0
    
    // 這樣驗證看得更清楚,會輸出++之前的m_iX值
    cout << (coor1++).m_iX << ",";
    cout << (coor1++).m_iY << endl;
    
    return 0;
}

6.二元運算符的重載

+(加號)的重載,也有兩種重載的方法:

  1. 成員函數重載
  2. 友元函數重載

對於此例來說,採用友元函數重載能說明得更加清楚。

1.加號的重載-成員函數重載:

// 聲明
class Coordinate{
public:
    Coordinate(int x,int y);
    
    // 返回對象作爲結果,參數是一個對象引用常量,
    // const是設計上的規範,我們在加的過程中並不希望修改加數本身的值
    Coordinate operator+(const Coordinate &coor);
    
private:
    int m_iX;
    int m_iY;
}

// 實現
Coordinate operator+(const Coordinate &coor){
    
    // 臨時對象,用來保存相加的結果
    Coordinate temp;
    
    temp.m_iX = this->m_iX + coor.m_iX;
    temp.m_iY = this->m_iY + coor.m_iY;
    
    // 返回結果(臨時對象)
    return temp;
}

// 調用
int main(){
    
    Coordinate coor1(3,5);
    Coordinate coor2(4,7);
    Coordinate coor3(0,0);
    
    coor3 = coor1 + coor2; // coor1.operator+(coor2);coor2前面還有一個隱藏參數,就是this指針,指向當前對象
    
    return 0;
}

2.加號的重載-友元函數重載:

// 聲明
class Coordinate{
    
    // 加const是設計上的規範,我們在加的過程中並不希望修改加數本身的值
    friend Coordinate operator+(const Coordinate &c1,const Coordinate &c2);
    
public:
    Coordinate(int x,int y);
private:
    int m_iX;
    int m_iY;
}

// 實現
Coordinate operator+(const Coordinate &c1,const Coordinate &c2){
    
    // 臨時對象,用來保存相加的結果
    Coordinate temp;
    
    temp.m_iX = c1.m_iX + c2.m_iX;
    temp.m_iY = c1.m_iY + c2.m_iY;
    
    return temp;
}

// 調用(和利用成員函數重載的調用一樣,但過程略有不同)
int main(){
    
    Coordinate coor1(3,5);
    Coordinate coor2(4,7);
    Coordinate coor3(0,0);
    
    coor3 = coor1 + coor2; // operator+(coor1,coor2);
    
    return 0;
}

<<負號的重載:

這個用法也是規定的,和其他的略有不同。

**問題:**可以使用成員函數進行重載嗎?不行,應該使用友元函數進行重載。

因爲重載函數的第一個參數也必須是ostream&,所以不能用成員函數進行重載,因爲成員函數的第一個參數是this指針(隱藏的)。

// 聲明
class Coordinate{
    
    // 利用友元函數進行重載
    // 返回值必須是ostream&
   	// 第一個參數也必須是ostream&
    // 之後是要輸出的對象
    friend ostream& operator<<(ostream &out,const Coordinate &coor);

public:
    Coordinate(int x,int y);
private:
    int m_iX;
    int m_iY;
}

// 實現
ostream& operator<<(ostream& out,const Coordinate& coor){
    
    // 將原來用cout的地方換成out
    out << coor.m_iX << "," << coor.m_iY;
    // 返回out
    return out;
}

// 使用
int main(){
    
    Coordinate coor(3,5);
    cout << coor; // operator<<(cout,coor);
    
    return 0;
}

[ ]索引運算符的重載:

**問題:**可以使用友元函數進行重載嗎?不行,應該使用成員函數進行重載。

作爲索引運算符來說,他的第一個參數必須是this指針,因爲只有第一個參數是this指針,才能夠傳入索引,才能使這個索引所表達的是當前這個對象當中的成員。

但是友元重載,第一個參數可以是this指針,也可以是其他的值。所以不能使用友元函數進行重載。

// 聲明
class Coordinate{
    
public:
    Coordinate(int x,int y);
    
    int operator[](int index);
    
private:
    int m_iX;
    int m_iY;
}

// 實現
int Coordinate::operator[](int index){
    
    if(0 == index){
        return m_iX;
    }
    if(1 == index){
        return m_iY;
    }
    // 還可以加其餘索引的處理...
}

// 使用
int main(){
    
    Coordinate coor(3,5);
    cout << coor[0]; // coor.operator[](0);
    cout << coor[1]; // coor.operator[](1);
    
    return 0;
}

小總結:

  1. 運算符重載可以使運算符具有新的功能。
  2. 運算符重載使用關鍵字operator
  3. 所有的運算符都可以既使用友元函數重載和成員函數重載。有些運算符必須使用成員函數重載,有些則必須使用友元函數重載。
  4. 運算符重載需要區分前置++重載和後置++重載。

6.5.補充:運算符重載和友元函數的問題

爲什麼臨時對象可以直接訪問到私有成員?

頭文件:

`class` `Coordinate {` `    ``// 利用友元函數進行+號重載``    ``friend` `Coordinate operator+(``const` `Coordinate c1,``const` `Coordinate c2);` `public``:``    ``// 構造函數,帶初始化參數``    ``Coordinate(``int` `x,``int` `y);` `    ``int` `getX();``    ``int` `getY();` `private``:``    ``// 私有屬性``    ``int` `m_iX;``    ``int` `m_iY;``};`

cpp文件:

`#include "Coordinate.h"` `Coordinate operator+(Coordinate c1,Coordinate c2){` `    ``Coordinate temp(0,0);` `    ``temp.m_iX = c1.getX() + c2.getX();``    ``temp.m_iY = c1.getY() + c2.getY();` `    ``return` `temp;``}`

爲何這裏可以直接使用 temp.m_iX ?

答案:

對象直接訪問自己的私有成員這種用法絕對是錯的,不要這麼使用。可以藉助友元類/友元函數類自己的成員函數進行訪問。

我們在Coordinate類中聲明瞭友元函數operator+(),友元函數在訪問權限上和類內函數比較相似,可以對這個類的所有數據成員進行訪問。

// 驗證友元函數中創建的對象是否可以訪問自己的私有成員。
// 結論:可以
 
#include <iostream>
 
using namespace std;
 
class hehe{
 
    // hehe類的友元函數
    friend void heheFriend(hehe &h);
 
public:
    int getxx(){ return xx; }
    int getyy(){ return yy; }
private:
    int xx;
    int yy;
};
 
void heheFriend(hehe &h){
 
    // 友元函數可以訪問類的所有成員,包括私有
    h.xx = 1;
    h.yy = 2;
 
    // 【友元函數中創建的對象h2可以訪問自己的私有成員】
    hehe h2;
    h2.xx = h.xx;
    cout << "h2.xx = " << h2.xx << endl;
}
 
 
int main() {
 
    hehe h1;
 
    // 無法直接訪問私有成員
    //h1.xx; // 錯誤提示:'xx' is a private member of 'hehe'
    //h1.yy; // 錯誤提示:'yy' is a private member of 'hehe'
 
    // 調用友元函數,進行函數成員賦值
    heheFriend(h1);
    cout << "h1.xx = " << h1.getxx() << endl;
 
    return 0;
}
/*
 * 輸出結果:
 * h2.xx = 1
 * h1.xx = 1 
 */

7.函數模板

函數模板和類模板關鍵字:

templatetypenameclass,其中 typenameclass起到的作用是相同的,並且可以混用。

關鍵字的使用1:

// 函數模板
// 通過template聲明函數的模板
// 通過class來聲明一個參數,這個參數就能表明這是一種類型
template <class T>
T max(T a, T b){
    return (a>b)?a:b;
}

// 模板函數(模板的使用),通過函數模板生產出來的函數
int ival = max(100,99); // 自動生成int數據類型
char cval = max<char>('A','B'); // 用<char>指定數據類型

關鍵字的使用2:

// 函數模板
template <class T>
void swap(T &a,T &b){
	T tmp = a; a = b; b = tmp;    
}

// 模板函數
int x = 20,y = 30;
swap<int>(x,y); // 用<int>指定數據類型

變量作爲模板參數:

// 函數模板
template <int size>
void display(){
	cout << size << endl;
}

// 模板函數
display<10>();

多參數函數模板:

// 函數模板
// 後面的typename也不能省略
template <typename T,typename C>
void display(T a,C b){
    cout << a << " " << b << endl;
}

// 模板函數
int a = 1024;string str = "hello world!";
display<int, string>(a,str);

函數模板定義中的混用:

// typename和class混用
template <typename T,class >

// 和變量混用
template <typename T,int size>
void display(T a){
	for(int i = 0;i < size;i++){
		cout << a << endl;
	}
}
display<int,5>(15);

小總結:

  1. 函數模板的參數個數可以是一個也可以是多個。(模板的參數是指<>中的內容)
  2. 函數模板的參數個數可以爲零個不可以爲零個參數,參數個數如果爲0個,則沒有必要使用函數模板。
  3. 使用函數模板時,需要指定模板參數,此時的函數稱爲模板函數。
  4. 當需要定義多個功能相同,數據類型不同的函數時,可以使用函數模板來定義。

8.類模板

類模板的.h和.cpp文件:

在C++中,模板代碼不能分離編譯(不能寫成.h+.cpp這種形式,只能把所有的代碼都寫在.h文件中使用),不然部分編譯器無法通過編譯。在使用的時候,只需要把.h文件include
""進當前程序中。

類模板的定義與使用1:

template<class T>

class MyArray{
public:
    // 1.類內定義
    void display();
private:
    T *m_pArr;
}
// 2.類外定義
// 類外定義類名後面需要添加<>
// 每定義一個成員函數,都要在這個成員函數前面添加template<......>
template<class T>
void MyArray<T>::display(){
    ......
}

// 使用
int main(){
    
    MyArray<int> arr;
    arr.display();
    return 0;
}

類模板的定義與使用2:

寫的時候需要特別注意各種修飾符、限定符、返回值類型,很容易寫錯。

#include <iostream>
using namespace std;

/**
 * 定義一個矩形類模板Rect
 * 成員函數:calcArea()、calePerimeter()
 * 數據成員:m_length、m_height
 */
template<typename T>
class Rect
{
public:
    Rect(T length,T height);
    T calcArea();
    T calePerimeter();
public:
	T m_length;
	T m_height;
};

/**
 * 類屬性賦值
 */
template<typename T>
Rect<T>::Rect(T length,T height)
{
	m_length = length;
	m_height = height;
}

/**
 * 面積方法實現
 */
template<typename T>
T Rect<T>::calcArea()
{
	return m_length * m_height;
}

/**
 * 周長方法實現
 */
template<typename T>
T Rect<T>::calePerimeter()
{
	return ( m_length + m_height) * 2;
}

// 使用
int main(void)
{
	Rect<int> rect(3, 6);
	cout << rect.calcArea() << endl;		// 輸出:18
	cout << rect.calePerimeter() << endl;	// 輸出:18
	return 0;
}

小總結:

  1. 定義一個類模板就相當於定義了一系列功能相同類型不同的類。
  2. 定義類模板需要使用關鍵字template。
  3. 定義類模板的參數可以使用typename和class,但不能混用可以混用
  4. 模板參數既可以是類型,也可以是變量。

9.標準模板庫STL(Standard Template Lib)

vector向量

**本質:**對數組的封裝

**特點:**讀取快速,讀取能在常數時間內完成,數據插入慢,如果插入數據,後面數據的位置都要移動。

初始化:

[外鏈圖片轉存失敗(img-8yBYgdSb-1563352671639)(./images/muke_C++/014.png)]

常用操作:

[外鏈圖片轉存失敗(img-Wy4kKhuO-1563352671640)(./images/muke_C++/015.png)]

向量的遍歷:

除了在for、while中使用下標進行遍歷,還可以使用迭代器

// for遍歷
for(int i = 0;i < vec.size();i++){
    cout << vec[i] << endl;
}

迭代器(iterator)及其使用方法:

int main(){
    
    vector vec;
    vec.push_back("hello");
    
    // 定義、初始化迭代器iterator
    vector<string>::iterator citer = vec.begin();
    // 使用迭代器遍歷向量
    for( ;citer != vec.end();citer++){
        cout << *citer << endl;
    }
    
    return 0;
}

鏈表(list)

**特點:**數據插入速度快,查詢較慢。

操作和vector向量類似,也可以使用迭代器,但不能用下標循環遍歷。

映射(map)

鍵值對,有點類似數組。

// 創建一個映射
map<int,string> m;

// 創建映射關係
pair<int,string> p1(10,"shanghai");
pair<int,string> p2(20,"beijing");

// 將創建的映射關係插入映射中
m.insert(p1);
m.insert(p2);

// 調用映射
cout << m[10] << endl;
cout << m[20] << endl;

也可以使用字符串作爲索引:

map<string,string> m;

pair<string,string> p1("SH","shanghai");
pair<string,string> p2("BJ","beijing");

m.insert(p1);
m.insert(p2);

cout << m["SH"] << endl;
cout << m["BJ"] << endl;

映射的遍歷:

**注意:**打印是按索引(key)的順序打印的,如“A”,先於“B”打印。

// 使用迭代器進行遍歷
map<int,string>::iterator itor = m.begin();
for(;itor != m.end();itor++){
    cout << itor->first << endl;	// 輸出key
    cout << itor->second << endl;	// 輸出value
    cout << endl;
}

小總結:

  1. vector是對數組的封裝,所以一旦對象被實例化,其大小就不能改變了 大小可以根據元素數量改變
  2. list的特點是數據插入速度快。
  3. map需要與pair一起使用,用來存儲多個key-value對。
  4. 不同廠商的標準模板庫的實現細節可以不同,基本用法及原理相同。

練習:

// 使用vector存儲數字3,6,8,4,並遍歷。
// 使用map存儲S-Shang Hai   B-Bei Jing    G-Guang Zhou,並遍歷
#include <vector>
#include <map>
#include <string>
#include <iostream>
using namespace std;

int main(void)
{
    // 使用vector存儲數字:3、4、8、4
    vector<int> vec;
    vec.push_back(3);
    vec.push_back(4);
    vec.push_back(8);
    vec.push_back(4);
    
    //循環打印數字
    vector<int>::iterator citer = vec.begin();
    for( ; citer != vec.end(); citer++){
        cout << *citer << endl;
    }
    
    // 使用map來存儲字符串鍵值對
    map<string, string> m;
    
    pair<string,string> p1("S","Shang Hai");
    pair<string,string> p2("B","Bei Jing");
    pair<string,string> p3("G","Guang Zhou");
    m.insert(p1);
    m.insert(p2);
    m.insert(p3);
  
    // 打印map中數據
    map<string,string>::iterator citer2 = m.begin();
    for( ; citer2 != m.end(); citer2++){
        cout << citer2->first << endl;	// key
        cout << citer2->second << endl;	// value
    }
    
    return 0;
}
/* 輸出:
3
4
8
4
B
Bei Jing
G
Guang Zhou
S
Shang Hai
*/

**注意:**打印是按索引(key)的順序打印的,如“A”,先於“B”打印。

本篇爲視頻教程筆記,視頻如下:

C++遠征之模板篇

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章