c++高級功能學習筆記

面向對象的三大特徵:封裝+多態+繼承

一、C++之封裝上

1.c++類 封裝

(1) 原始類賦值:

N.name="myy";
N.age=10;

正確賦值,將賦值封裝進類定義的函數,這樣就可以對賦值內容進行是否合法限制

class Sudent
{
    public:
    void setAge(int_age)
    {
        if(int_age>0&&int_age<100)
        {
            age=int_age;
        }
        else{...}
    }
};

(2) 若希望內部內容只被讀取而不被改變–只讀屬性

class Car
{
    public:
        int get_num(){return num;}
    private:
        int num;

};

2. 內聯函數和類內定義

  • 關鍵字:inline
    inline void fun {cout<<“Hello”<<endl;}
  • Inline函數省去了編譯時函數調用的步驟,使編譯更高效,但僅限於結構簡單的函數,複雜函數編譯器拒絕執行inline。
  • 類內定義
    • 類內定義:將函數聲明及定義寫在類內,對於簡單函數會相同。

3.構造函數初始化及定義

//.h中聲明
class Car
{
    public:
    Car(int num=1, string name="BMW");
};
//.cpp中定義,num, na

me 不用再初始化
Car::Car(int num, string name):n_num(num), n_name(name){}

4. 拷貝構造函數

  • 當我們對自定義類進行拷貝操作時,不會重新調用構造函數,而是調用編譯器自動生成的拷貝構造函數(如果沒有自定義拷貝構造函數的話)。
  • 如果想自己構造拷貝構造函數,格式如下:
  • 定義格式:類名(const類名&變量名)
  • 如果沒有自定義拷貝構造函數,系統會自動生成一個默認的。
  • 構造函數分類:
    • 無參構造函數
      • 默認構造函數
    • 有參構造函數
      • 參數帶默認值
      • 參數無默認值
  • 代碼示例:
//.h聲明
  class Teacher
  {
      public:
      Teacher (string name="Jim", int age=1);
      Teacher(const Teacher &tea)();//拷貝構造
      int age;
      string name;
  };
  //Teacher.cpp
   Teacher::Teacher(const Teacher &tea)
   {}
  //main.cpp使用
  //*拷貝構造在參數傳遞的使用中也能用到,代碼示例test函數,內部的變量定義t生成時用的拷貝構造函數
  int main()
  {
    Teacher t1;
    Teacher t2=t1;
    Teacher t3(t1);
    return 0;
  }
  • 拷貝構造函數還會以參數傳遞的方式進行使用
void test(Teacher t)//
  {

  }
  int main(void)
  {
      Teacher t1;
      tes(t1);//此操作使用了拷貝構造函數。
  }

二、C++封裝下

2.1 對象數組

int main(void)
{
    Teacher t[3];
    t[3].name="lisa";//從棧中建立對象數組
    Teacher *p=new Teacher[3];
    p[0].name="Lisa";
    p[1].name="Tom";
    p[2].name="Jane";
    delete []p;//從堆中建立對象數組
    p=NULL;//p++即指向下一個對象元素,但是切記delete時,p的位置要回到第一個數組元素位置那。另外,P最後要指向NULL。
}

2.2 對象成員

2.3 深拷貝與淺拷貝

(1) 淺拷貝:對於非指針類型,直接拷貝值;對於指針類型,拷貝指針的值,而非指針指向的值,該種情況會造成程序崩潰。
(2) 深拷貝:對於指針類型的值,新建一個指針,並將待拷貝元素指針所指向的值拷貝過來。

  • 代碼示例
//淺拷貝,無指針參數
class Array
{
  public:
  Array()Array(const Array &a)
  {
      m_ix=a.m_ix;
      m_iy=a.m_iy;
  }
  private:
  int m_ix;
  int m_iy;
}
//深拷貝,帶指針拷貝
class Array
{
  public:
  Array()
  {
    m_iCount=5;
    m_iP=new int[m_iCount];
  }
  Array(const Array &a)
  {
      m_iCount=a.m_iCount;
      m_iP=new int[m_iCount];
      for(int i=0;i<m_iCount;i++)
      {
        m_iP[i]=a.m_iP[i];
      }//將指針所指向的內容進行拷貝
  }
  private:
  int* m_iP;
  int m_iCount;
}

2.4 this指針–類變量的地址

(1) 傳入的參數和類的數據成員不能重名,否則報錯;

Array(int len){this->len=len;}//這樣就可以實現

2.5 const 使用-帶有const的,就不允許改變成員變量

(2) 常成員函數

  • 函數不能對數據成員進行修改;
  • 常量構造函數,賦值只能用初始化列表方式
    • const Array::Array(int a):num(a){}
  • 格式: void change() const;
  • 重載: void change(); void change() const;互爲重載函數,當變量定義爲常量時,則調用常量函數,鬥則調用普通函數。
  • const 函數重載目的是爲了防止用戶自定義一個const類,然後再調用類函數時出錯,所以做的一個備用完善。如果用戶不需要類const,則不需要該代碼

2.6 常指針與常引用

(1) 常指針

  • 一般函數的this指針要求同時具有讀和寫權限,然而加const的變量只能有讀權限,所以const變量調用函數時會有衝突報錯,即使調用的函數不會改變成員變量的值,也因爲有潛在風險,畢竟編譯器不知道你在函數裏定義了哪些操作,所以統統報錯,只有函數後面加上const時,保證自己不會修改變量,此時編譯器纔不會報錯。

(2) 易混淆情況:

  • const Array *p=&n;
  • Array * const p1=&n;
  • 以上兩個const指針含義不同,第一個是指指針指向的變量是常成員變量,該變量不能再進行修改值的操作; 而第二個定義的是常指針,即指針不能再指向其他變量。

(3) 常引用:
Array c1(2);
const Array &c2=c1;
此時c2是c1的別名,但是與c1不同的是,c2只有只讀權限。

三、繼承篇

3.1 繼承篇

  • 前提:要繼承的類,要完全包含於父類。子類只需要再補充自己特有的函數即可。(基類->派生類)
  • 內存關係:子類的內存等於父類的內存大小加上自己的特有的函數的內存大小。
  • 語法:
class Worker : public Person
  {
  
  };
  • 在一個類中調用別的類,析構時先析構該類,再析構調用的類,類似層層剝繭;
  • 而析構一個繼承了父類的子類時,要先析構子類,再析構父類,類似從尾到源式順序。

3.2 三種繼承

(1) 共有繼承 class A:public B
(2) 保護繼承 class A: protected B
(3) 私有繼承 class A: private B

  • 公有繼承

    • 父類的保護成員,可以被保護式的繼承給子類,但是外部對象不可訪問;
    • 父類的私有成員,不可被繼承,因爲無法訪問。
  • 保護繼承

    • 父類的公有成員和保護成員,都會被子類繼承爲保護成員
    • 私有成員同上
  • 私有繼承

    • 父類的公有和保護成員,會被子類繼承爲私有成員;
    • 私有成員不被繼承\

(4) has a 關係,不同於is a; 私有繼承也是一種has a 關係

3.3 隱藏

  • 父子關係
  • 成員同名
  • 隱藏: 當子類有與父類同名的函數或者數據變量時,定義的子類對象調用時會調用子類裏的函數。而如果想要調用父類的變量時,格式爲
m.setName();//子類對象
m.FL::setName();
  • 對於隱藏的兩個對象,不會因爲是否傳入參數不同而形成重載,調用父類函數,只能用隱藏的語法。
    小知識補充:
    #include “”,用雙引號則編譯器會從文件目錄去找頭文件;如果用<>,則編譯器會從安裝包裏包含的文件庫找頭文件。

  • 派生類可以賦值給基類,但是基類不能賦值給派生類。

  • 當子類給父類對象初始化時,父類只能接收兩者共同部分的函數和數據值,對於子類獨有的函數,父類不能被初始化

  • 當父類的指針指向子類對象時,也只能訪問到兩者的公共部分,而不能訪問到子類獨有的部分

3.4 多繼承和多重繼承

(1)多重繼承:多代繼承
(2)多繼承:一個子類有多個父類
代碼示例

class Worker{};
class Farmer{};
class MirgrantWorker:public Worker, public Farmer{};


(3) 菱形繼承
類A
| |
類B 類C
| |
類D

  • 類D中由於繼承可能會有兩份類A,造成不必要的內存佔用,如何避免內存開銷?-虛繼承
  • 解決辦法:
  • class B:virtual public A;
  • class C:virtual public A;
  • class D:public B,public C

四、多態

4.1 虛函數–靜態多態VS動態多態

多態形式是父類指針指向子類對象,所以如果子類中有指針數據成員,那個在子類構造時會申請一塊內存。父類在析構時並不能析構子類的內容,會造成內存泄漏,所以父類需要虛析構函數
(繼承特性:如果delete父類指針,則只會銷燬父類的函數;而delete子類指針,則父類和子類定義都會被銷燬)
(1) 靜態多態(早綁定):同一對象收到相同的消息卻產生不同的函數調用,一般通過***函數重載***來實現,在編譯時就實現了綁定,屬於早綁定。

(2) 動態多態(晚綁定):不同對象在收到相同消息時產生不同的動作,一般通過虛函數來實現,只有運行時才能實現綁定,屬於動態綁定,一般通過函數覆蓋來實現

(3) 覆蓋: 虛函數允許子類重新定義成員函數,而子類重新定義父類的做法稱爲覆蓋。若不是虛函數,僅父類和子類有同樣函數,是爲隱藏。

4.2 虛析構函數

(1) 動態多態在父類指針釋放子類對象時造成內存泄漏,爲了防止而在父類中使用虛析構函數。

(2) 根據VS2019實踐,即使子類對象中沒有指針類型,只要使用了多態,析構函數就得用virtual;

(3) 虛函數可被繼承,當子類中定義的函數與父類中虛函數聲明相同時,該函數就是虛函數;
(4) virtual使用注意事項:

  • 普通函數不能使用,即不在類中的函數;
  • static 靜態成員函數不能使用。
  • 不能使用內聯函數,會被編譯器視爲純虛函數;
  • 構造函數不能爲虛函數\

(5) 虛函數與虛析構函數原理

  • 父類存在一個虛函數指針,指向一個虛函數表,在表中存有各虛函數的地址。因此開始執行時,當執行到虛函數,編譯器會從虛函數表中找虛函數地址;對於在子類中覆蓋的虛函數,子類也存在一個虛函數表,只不過對應位置上的指針地址改爲子類所覆蓋的函數地址。虛析構函數同理。
    尋址過程類似如下:
    shape
    |vftable|–>|…|
    |m_iEdg|         |calcArea_ptr|–>|calcArea|
    |m_dRR|\

(6) 代碼證明虛函數表的存在
概念說明

  • 對象的大小:類裏定義的函數不佔內存大小,只有數據成員佔內存。對於沒有任何數據成員的對象,爲表示其存在,編譯器給其內存大小爲1;對於存在一個int型的對象,其內存佔用大小爲int型大小4字節。
  • 對象的地址:——
  • 對象成員的地址:在對象地址的頭部開始
  • 虛函數表的指針: 在有虛函數情況下,實例化一個對象時,對象佔用內存的第一塊就是虛函數表的指針,佔據內存大小4字節,然後依次是該對象的數據成員。
  • 如果子類沒有覆蓋父類的虛函數,則兩張虛函數表中,某一虛函數指針指向同一個函數。

4.2純虛函數和抽象類

(1)定義:只有函數聲明,沒有定義,且聲明後加等於0;

  • 格式:
    virtual double calcPerimeter()=o;//純虛
    virtual double calcArea(); //虛函數
    

(2)虛函數表中,表指針指向的純虛函數值爲0; 而虛函數則指向一個具有實際意義的函數。
(3)抽象類: 含有純虛函數的類叫做抽象類

  • 由於含有純虛函數原因,抽象類無法實例化對象
  • 抽象類的子類,如果沒有定義父類的純虛函數,那麼它也是抽象類,無法進行實例化;
    (4)**接口類:**僅含有純虛函數的類稱爲接口類
  • 及沒有數據成員,只有純虛函數;
  • 實際使用中,接口類更多用於表達一種能力或協議。
  • 比如父類定義了一些函數特性,那麼子類必須實現這些函數,才從概念上說明子類屬於父類。
  • Note that:
    • 抽象函數中只有純虛函數,沒有數據成員,構造函數和析構函數。
    • 接口類最常見用法是在定義全局函數時限制輸入對象的類型,但是傳入的所有數據都可以安全調用抽象類的純虛函數,因爲肯定已經被定義過了。
    • 可以使用接口類指針指向子類對象來實例化一個對象,並調用子類中實現的接口類中的純虛函數。
void flyMatch(Flyable *a, Flyable *b)
{
  a->takeOff();
  a->land();
  b->takeOff();
  b->land();
}  

ctrl+k+u去掉註釋;
ctrl+k+c加註釋

4.3 RTTI(Run-Time Type Identification)-運行時類型識別

RTTI的作用就是需要對對象成員進行動態判斷時,用關鍵字來確定對象的動態類型。如引入的是父類類型指針指向的子類對象,但是繼承父類的子類有很多,需要實時的根據不同的子類執行不同的操作,此時就需要RTTI了
(1)關鍵字:dynamic_cast,以下是其注意事項:

  • 只能應用於指針和引用的轉換;
  • 要轉換的類型中必須包含虛函數;
  • 轉換成功返回子類地址,失敗返回NULL;
    (2)關鍵字: typeid,以下是其注意事項:
  • type_id返回一個type_info對象的引用;
  • 如果想通過基類指針獲得派生類的數據類型,基類必須帶有虛函數
  • 只能獲取對象的實際類型。
    (3)示例代碼
void doSomething(Flyable *obj)//需要轉換的只能是指針
{
  if(typeid(*obj)==typeid(Bird))
  {
    Bird *b=dynamic_cast<Bird *>(obj);//要轉換的類型中必須包含虛函數,子類繼承父類的函數也是虛函數
  }
  if(typeid(*obj)==typeid(Plane))
  {
    Plane *p=dynamic_cast<Plane*>(obj);//如果想通過基類指針獲得派生類數據類型,基類必須帶有虛函數
  }
}

4.4 C++異常處理

對可以預見的錯誤進行相應的處理,否則交由編譯器處理的話會直接造成程序崩潰。
(1)關鍵字:try…catch… throw

  • 說明:try.catch:將主邏輯放在try塊裏,異常處理模塊放在catch裏。
  • 在main函數中,用try,catch塊進行異常捕獲
  • 常見的異常有:數組溢出+除數爲0+內存不足
    (2)實踐:可以通過定義父類作爲接口,然後接受各種子類異常。

五、模板

5.1 友元函數和友元類

(1)友元全局函數:函數定義在全局,且在類中聲明爲友元,則在該函數中可以調用類的private成員;
(2)友元成員函數:定義在類A中,且在類A的定義前要加入“class B;”,以告知編譯器不需要報錯。該函數需要在另一個類B中聲明爲其友元函數,且在B中需要Include 類A的頭文件。形式爲

#include "A_class.h"
class B_class
{
public:
friend void A_class::printA(B_class &t);
...
};

(3)友元類:與友元函數類似,只需在類裏面聲明即可。形式爲:

class Circle;
class Coordinate
{
  friend Circle;
  public:
  ...
};

將Circle定義爲友元類後,我們就可以在circle類中定義coordinate的對象,通過該對象,調用其私有數據類型和私有函數。
(4)

  • 友元關係不可傳遞;
  • 友元關係單向;
  • 友元聲明的形式及數量不受限制
  • 友元只是封裝的補充,不推薦用,因爲減弱了類的封裝性。

5.2 類中static

  • 應用場景:一個公司的系統,每新建一個用戶,統計用戶的num變量就++, num變量不依賴新用戶或舊用戶的生成或消失而生成或消失,但是卻會因爲新建一個用戶而加一,註銷一個用戶而減1。外界可以隨時調用靜態成員查看num值。它依賴類存在而存在,不依賴對象存在而存在。
  • 靜態數據成員
    • 注意事項:必須初始化;
    • 可被非靜態和靜態函數均可調用。
  • 靜態成員函數
    • 注意事項:不能調用非靜態數據成員;
    • 形式:
    class A
    {
      public:
      A(){num++;}
      ~A(){num--;}
      static num;
      static getNum{return num;}
    };
    int A::num=0;
    
  • 調用靜態函數和靜態成員時形式:
    //方式一
    int main(void)
    {
      cout<<A::getNUm()<<endl;
      cout<<A::num<<endl;
    }
    //方式二
    int main()
    {
      A a;
      cout<<a.num<<endl;
      cout<<a.getNm<<endl;
    }
    

5.3 運算符重載

(1)關鍵字:operator; 包括一元運算符重載、二元運算符重載等
(2)以一元運算符(只需與一個變量進行運算)重載的-(負號)、++兩個符號爲例;

  • -(負號)的重載:友元函數重載+成員函數重載
    -負號函數重載代碼示例
//成員函數重載
class coordinate
{
  public:
  coordinate();
  ~coordinate();
  coordinate & operator-()
  {
    m_x=-m_x;
    m_y=-m_y;
  }
  privateint m_x;
  int m_y;
};
//友元函數重載
class coordinate
{
  friend coordinate & operator-(coordinate &c);
  {
    m_x=-m_x;
    m_y=-m_y;
  }
  public:
  coordinate();
  ~coordinate();
  privateint m_x;
  int m_y;
};
//friend function realization
//coordinate..cpp
coordinate & operator-(coordinate &c)
{
  c.m_x=-c.m_x;
  c.m_y=-c.m_y;
  return c;
}

++符號重載示例

  • 首先講述一下,前置++,“++a”,表示本次操作結束後,a的值比原來大一;後置++,“a++”,表示的是本次執行結束後a的值不變,但是一旦執行下一條指令時a就會加一,值比原來大1。
  • 編譯器爲了區分這兩種++,在指令傳入時有所不同,這點需仔細對比兩者代碼。
  • 變量的返回也有不同,比如函數定義時,是否加引用&符號。
  • 以下編程示例中會着重講解,需要認真理解。
//前置++
class Coordinate
{
public:
  Coordinate& operator++()
  {
    ++m_x;
    ++m_y;
    return *this;
  }
};
//後置++
class Coordinate
{
public:
  Coordinate operator++(int)
  {
    Coordinate old(*this)//複製傳入的變量值
    ++(this->m_x);
    ++(this->m_y);
    return old;//也就是說本次執行返回變量未加一之前的值;等下一個使用該變量的代碼使用時,變量才變爲原來的+1值。
  }
};

(3) 二元運算符重載:成員函數重載和友元函數重載

  • 第一個典型例子是+號的重載(友元和成員函數都可進行重載)
  • 成員函數+號重載
class Coordinate
{
  public:
    Coordinate(int x,int y);
    Coordinate operator+(const Coordinate &coor)//this指針表示+號左邊值;coor爲傳入+右邊值,但是返回一個新值給等號左邊。傳入的值爲了保險起見,不能改變其值大小,所以加const.
    {
      Coorfinate m;
      m.m_x=this->m_x+coor.m_x;
      m.m_y=this->m_y+coor.m_y;
      return m;
    }
  private:
    int m_x;
    int m_y;  
};
  • 友元函數+號重載
class Coordinate
{
  friend Coordinate operator+(const Coordinate &coor1,const Coordinate &coor2)
  {
    Coordinate m;
    m.m_x=coor1.m_x+coor2.m_x;
    m.m_y=coor1.m_y+coor2.m_y;
    return m;
  }
  public:
    Coordinate(int x,int y);  
  private:
    int m_x;
    int m_y;  
};

//main.cpp
int main()
{
  Coordinate p1(2,3);
  Coordinate p2(3,4);
  Coordinate p3(0,0);
  p3=p1+p2;
  return 0;
}
  • “<<”輸出運算符重載(只能友元函數重載)
    • 成員函數不可進行重載的原因:因爲重載函數中首個參數必不包含對象的this指針,而是外部的cout的oostream類型引用,所以一定不能用成員函數進行重載。
    • 友元函數重載
class Coordinate
{
  friend ostream& operator<<(ostream &out, const Coordinate &coor)
  {
    out<<coor.m_x<<","<<coor.m_y;//該部分與cout形式一樣
    return out;//務必要返回
  }
  public:
    Coordinate(int x,int y);  
  private:
    int m_x;
    int m_y;  
};

//main.cpp
int main()
{
  Coordinate coor(3,5);
  cout<<coor;
}
  • []索引運算符(只能成員函數進行重載)該重載的更多運用在數組上
    • 因爲索引的第一個參數一定是對象的this指針,而不能是別的,所以不能用友元函數進行重載
    • 成員函數重載代碼實現:
class Coordinate
{
  public:
    Coordinate(int x,int y);  
    int operator[](int index)
    {
      if(index==0)
      {return m_x;}
      if(index==1)
      {return m_y;}
    }
  private:
    int m_x;
    int m_y;  
};

//main.cpp
int main()
{
  Coordinate c(3.5);
  cout<<c[0];
  cout<<c[1];
  return 0;
}

5.4 模板函數與模板類

(1) 爲什麼要引入模板?
對於只有參數類型不同,其他均相同的函數,爲了定義方便,將參數類型作爲變量傳入函數模板.
(2) 關鍵字:template typename class(typename 和 class可以混用)
(3)計算機中,如果僅僅寫出函數模板,而沒有使用它,那麼計算機是不會產生任何代碼數據。只有當去使用函數模板纔會產生實際代碼
(4) 函數模板及其語法

  • 類型作爲模板參數
  template<class T>
  T max(T a, T b)//注意term name:函數模板
    {
      return(a>b)?a:b
    }

  //使用
  int main()
  {
    int m=max(100,90);//編譯器可以自動根據檢測到的數據類型進行計算;
    //term name:模板函數
    char n=max<char>('A','B');//也可以自己強制生成
  }
  • 常量值作爲模板參數;需要注意的是不能使用浮點數,類,指針等作爲模板參數,而且必須是確定的值,不能是變量。
template<int size>
void display()
{
  cout<<size<<endl;
}
//使用
int main()
{
  display<10>();
}
  • 多參數函數模板
template<typename T,typename C>
void display(T a, C b)
{
  cout<<a<<""<<b<<endl;
}

template<class A, int size>//這部分決定了函數在使用時要給出的類型和變量值的結構形式
void max(A a)//該部分決定了函數括號內部的結構
{
  if(a>size)
  {
    cout<<a<<endl;
  }
  else
  {
    cout<<size<<endl;
  }
}
//使用
int main()
{
  int a=3; 
  char str='A';
  display<int,char>(a,str);//將聲明的都指定出來即可
  max<int,5>(a);
}
  • 函數模板與重載
    • 函數名相同,但輸入類型不同的函數模板不是函數重載,因爲在未使用之前,它們不會在內存中生成任何代碼,只有在使用的時候,生成了代碼,纔會形成重載
tempplate <typename T>
void display(T a);

tempplate <typename T,int size>
void display(T a);

tempplate <typename T>
void display(T a, T b);

(5) 類模板:適用於編寫數據結構相關代碼

  • 必須在頭文件中全部定義,無法做到.cpp/.h分別編譯;
  • 類模板外部定義的成員函數,每一個前面都需要加上模板<>聲明。
  • 語法
template<class T>
class MyArray
{
  public:
    void display(){...}//類內定義成員函數,與普通類無不同
    void setName(T mm);
    T Add(T a, T b);
    private:
    T *m_pArr;
};
template<class T>
void MyArray<T>::setName(T mm)//每一個函數都需要重申一次
{...}

template<class T>
T MyArray<T>::Add(T a, T b)
{...}

//使用時
int main()
{
  MyArray<int> arr;
}

情況二

template<class T, int KSize>
class MyArray
{
  public:
    void display(){...}//類內定義成員函數,與普通類無不同
    void setName(T mm);
    T Add(T a, T b);
    private:
    T *m_pArr;
};
template<class T, int KSize>
void MyArray<T,KSize>::setName(T mm)//每一個函數都需要重申一次
{...}

template<class T, int KSize>
T MyArray<T,KSize>::Add(T a, T b)
{
  a=b+KSize;
  return a;
}

//使用時
int main()
{
  int a=3;
  int b=4;
  MyArray<int,10> arr;
  arr.Add(a,b);//Add函數不需要再加<>類型聲明
}

5.5 標準模板類

(1)vector

  • vector v3(n,i);//含義爲包含n個值爲i的元素
  • vector v1(v3);//複製了一個v3
  • 常用函數
  empty()//返回是否爲空
  begin()//返回首個元素
  end()//返回末元素的下一個元素
  clear()//清空向量
  front()//第一個數據
  back()//最後一個數據
  size()//返回大小
  push_back()//將數據插入向量尾
  pop_back()//刪除向量尾部數據
  • 迭代器 iterator
  • 藉助迭代器可以實現標準模板內部的遍歷
  • 迭代器定義的元素一使用時一定要加, 這樣才表示前迭代器所指向的元素*
vector<string> vec;
vec.push_back('A');
vector<string>::iterator cite = vec.begin();
for(; cite!=vec.end();cite++)
{
  cout<<*citer<<endl;//
}

(2)鏈表

  • 鏈表的遍歷只能通過iterator進行,不能使用普通的for循環
  • 插入速度大於向量

(3)map 映射

  • key-value
  • 使用方法
  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的輸出有兩種方法,其中迭代器法需要注意。
    例子2
  map<string, string> m;
  pair<string, string> p1("S","shanghai");
  m.insert(p1);
  cout<<m["S"]<<endl;//
//只能用迭代器遍歷,且元素輸出要注意
  map<string, string>::iterator ite=m.begin();
  for(; ite<m.end();ite++)
  {
    cout<<ite->first<<endl;//鍵值
    cout<<ite->second<<endl;//value
  }

總結:

  • 類中可能定義的基本函數:
    • 構造、析構函數;
    • 拷貝構造函數(深/淺拷貝);//查詢
    • const等其他函數重載;
    • 靜態變量&靜態函數;
    • 虛函數/純虛函數;(虛函數用於繼承中的覆蓋(有指針變量的話需要虛析構函數)純虛函數用於做接口類型的類,是多個子類的父類,沒有析構和構造函數);
    • 運算符重載函數;
發佈了45 篇原創文章 · 獲贊 17 · 訪問量 4萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章