C++類模板與STL編程


1,學習目標

 

1.理解類模板的概念;
2.掌握類模板的定義、實例化過程,會運用類模板;
3.掌握棧類模板、鏈表類模板的使用;
4.理解STL編程的基本思想;
5.掌握STL容器的使用;
6.熟練使用STL算法;
7.理解STL函數對象;
  1. 類模板

 

模板是C++語言的重要特征,它能夠顯著提高編程效率。利用C++的函數模板和類模板,能夠快速建立具有類型安全的類庫集合和函數集合,進行大規模軟件開發,並提高軟件的通用性和靈活性。C++的 標准模板庫(standard template library,簡稱 STL)編程完全依賴模板的實現。
   
       類模板是能根據不同參數建立不同類型成員的類。類模板中的數據成員、成員函數的參數、成員函數的返回值可以取不同類型,在實例化成對象時,根據傳入的參數類型,實例化成具體類型的對象。類模板也稱模板類。
  
類模板定義的語法為:
 
template < 模板參數表 >
class 類名
{
        成員名;
};
  
   其中:
Ø template為模板關鍵字。
Ø 模板參數表中的類型為參數化(parameterized)類型,也稱可變類型,類型名為class (或typename);模板參數表中的類型也可包含普通類型,普通類型的參數用來為類的成員提供初值。
Ø 類模板中的成員函數可以是函數模板,也可以是普通函數。
 
       例如,下面定義了一個模板類Student,為了增強類的適用性,將學號設計成參數化類型,它可以實例化成字符串、整型等;將成績設計成參數化類型,它可以實例化成整型、浮點型、字符型(用來表示等級分)等;
  
template <class TNO, class TScore, int num>  // TNO,TScore 為參數化類型
class Student                     
{
  private:
        TNO StudentID[num];      //參數化類型數組,存儲姓名
  TScore score[num];      //參數化類型數組,存儲分數
  public:
  TNO TopStudent()     //普通函數
  { 
          return StudentID[0];
  }   
  int BelowNum(TScore  ascore)  //函數模板
  {
               return 0;
  }
  void sort()                  //普通函數
  {
  }
};
  
模板類的成員函數還可以在類外定義,其語法如下::
 
template < 模板參數表 >
類型    類名    < 模板參數名表 > ∷函數名 ( 參數表 )
{
        函數體 ;
}
  
其中:
Ø模板參數表與類模板的模板參數表相同。
Ø模板參數名表列出的是模板參數表中參數名,順序與模板參數表中的順序一致。
 
模板類Student的成員函數在類外實現如下:
 
template <class TNO, class TScore, int num>
class Student                     
{
  private:
      TNO StudentID[num];
               TScore score[num];
  public:
      TNO TopStudent(); 
      int BelowNum(TScore ascore);
      void sort();
};
template < class TNO, class TScore, int num >
int Student<TNO, TScore, num> :: BelowNum(TScore ascore)
{
   return 0;
}
template <class TNO, class TScore, int num>
void Student<TNO, TScore, num> :: sort()
{
}
template <class TNO, class TScore, int num>
TNO Student<TNO, TScore, num> :: TopStudent()
{
         return StudentID[0];
}

 

   一個類模板是具體類的抽象,在使用類模板建立對象時,才根據給定的模板參數值實例化(專門化)成具體的類,然后由類建立對象。與函數模板不同,類模板實例化只能采用顯式方式。
       類模板實例化、建立對象的語法如下:
  
   一個類模板是具體類的抽象,在使用類模板建立對象時,才根據給定的模板參數值實例化(專門化)成具體的類,然后由類建立對象。與函數模板不同,類模板實例化只能采用顯式方式。
       類模板實例化、建立對象的語法如下:
  
類模板名 < 模板參數值表 > 對象 1, 對象 2, , 對象 n;
  
    其中:
Ø 模板參數值表的值為類型名,類型名可以是基本數據類型名,也可以是構造數
    據類型名,還可以是類類型名。
Ø模板參數值表的值還可以是常數表達式,以初始化模板參數表中普通參數。
Ø模板參數值表的值按一一對應的順序實例化類模板的模板參數表。
  
class String {
  public:
char Str[20];
};
void main()
{
   Student<String, float ,100> S1; 
   S1.sort();
   Student<long, int, 50> S2;
   S2.TopStudent();
}
  
class Student                     
{
  private:
        String StudentID[100];
  float score[100];
  public:
  String TopStudent(); 
  int BelowNum(float ascore);
  void sort();
};
  
 
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
// p10_2.cpp *  單向鏈表的類模板 *
#include <iostream>
using namespace std;
template <class TYPE>
class ListNode
{
  private:
TYPE data;
ListNode * next;
     static ListNode    * CurNode;
     static ListNode    * head;
  public:
ListNode()
{
    next=NULL;
    head=CurNode=this;
}
ListNode(TYPE NewData)
{
    data=NewData;
    next=NULL;
}

2,STL編程

 

       STL(Standard Template Library),即標准模板庫,是一個高效的C++程序庫。STL是ANSI/ISO C++標准函數庫的一個子集,它提供了大量可擴展的類模板,包含了諸多在計算機科學領域里所常用的基本數據結構和基本算法,類似於Microsoft Visual C++中的 MFC(Microsoft Foundation Class Library)。
       從邏輯結構和存儲結構來看,基本數據結構的數量是有限的。對於其中的數據結構,用戶可能需要反復的編寫一些類似的的代碼,只是為了適應不同數據的類型變化而在細節上有所出入。如果能夠將這些經典的數據結構,采用 類型參數的形式,設計為 通用的類模板和函數模板的形式,允許用戶 重復利用已有的數據結構構造自己特定類型下的、符合實際需要的數據結構,無疑將簡化程序開發,提高軟件的開發效率,這就是STL編程的基本設計思想。
  
邏輯層次來看,STL中體現了 泛型化程序設計(generic programming)的思想,它提倡使用現有的模板程序代碼開發應用程序,是一種代碼的重用技術(reusability)。代碼重用可以提高軟件開發人員的勞動生產率和目標系統質量,是軟件工程追求的重要目標。許多程序設計語言通過提供標准庫來實現代碼重用的機制。STL是一個通用組件庫, 它的目標是將常用的數據結構和算法標准化、通用化,這樣用戶可以直接套用而不用重復開發它們,從而提高程序設計的效率。
 
       從 實現層次看,STL是一種 類型參數化(type parameterized)的程序設計方法,是一個基於模板的標准類庫,稱之為 容器類。每種容器都是一種已經建立完成的標准數據結構。在容器中,放入任何類型的數據,很容易建立一個存儲該類型(或類)的數據結構。
 
       STL主要由五個部分組成,分別是容器(container)、迭代器(iterator)、適配器(adaptor)、算法(algorithm)以及函數對象(function object)。
  
在STL程序設計中, 容器(container)就是 通用的數據結構。容器用來承載不同類型的數據對象,就如同現實生活中,人們使用容器用來裝載各種物品一樣,但C++中的容器還存在一定的“數據加工能力”,它如同一個對數據對象進行加工的模具,可以把不同類型的數據放到這個模具中進行加工處理,形成具有一定共同特性的數據結構。例如將int型、char型或者float型放到隊列容器中,就分別生成int隊列、char型隊列或者float型隊列,它們都是隊列,具有隊列的基本特性,但是具體數據類型是不一樣的。
 
       STL容器主要包括 向量( vector )、列表( list )、隊列( deque )、集合( set/ multiset )和映射( map/multimap 等。STL用模板實現了這些最常用的數據結構,並以算法的形式提供了對這些容器類的基本操作。
 
       STL中的所有容器都是 類模板,是一個已經建立完成的抽象的數據結構,因此可以使用這些容器來存儲任何類型的數據,甚至是自己定義的類,而無需自己再定義數據結構。例如利用deque容器,就很容易建立一個隊列。
 1,順序容器
 
容器類名
特性
何時使用
頭文件
vector
(向量)
在內存中占有一塊連續的空間,存儲一個元素序列。可以看作一個可自動擴充的動態數組,而且提供越界檢查。可用[]運算符直接存取數據。
需要快速查找,不在意插入/刪除的速度快慢。能使用數組的地方都能使用向量。
<vector>
list
(列表)
雙向鏈接列表,每個節點包含一個元素。列表中的每個元素均有指針指向前一個元素和下一個元素。
需要快速的插入/刪除,不在意查找的速度慢,就可以使用列表。
< list >
deque
(雙端隊列)
在內存中不占有一塊連續的空間,介於向量和列表之間,更接近向量,適用於由兩端存取數據。可用[]運算符直接存取數據。
可以提供快速的元素存取。在序列中插入/刪的速度除較慢。一般不需要使用雙端隊列,可以轉而使用vector或list。
< deque >
 
容器類名
特性
何時使用
頭文件
set
(集合)/
multiset
(多集)
set是一個元素集合。集合中的元素按有序的方式存儲。set中沒有重復的元素,但multiset中允許有重復的元素。
需要使用元素集合,而且對元素的查找、插入和刪除操作都較為頻繁時,就可以使用set/multiset。
<set>
map
(映射)/
multimap
(多映射)
map是{鍵(key),值}對的組成的集合。集合中的元素按鍵排列。multimap是允許鍵/值對有重復的集合。map和multimap的關系如同set和multiset之間的關系
如果希望將鍵/與值相關聯就可以使用map/muitimap。
< map >
3,STL算法  
 
       算法( algorithm 就是一些常用的數據處理方法,如向容器中插入、刪除容器中的元素、查找容器中的元素、對容器中的元素排序、復制容易中的元素等等,這些數據處理方法是以函數模板的形式實現的實現的。        算法之美就在於它們不僅獨立於底層元素的類型,而且也獨立於所操作的容器,利用這些已經定義的算法和迭代器,程序設計人員可以方便靈活地地存取容器中存儲的各種數據元素。         在STL中,算法的“神奇之處”在於:算法並非容器的一部分,而是工作在迭代器基礎之上,通過迭代器這個“ 中間人”存取容器中的元素,算法並沒有和特定的容器進行綁定。        在傳統的軟件開發方法中,算法與數據類型、數據結構緊密耦合,缺乏通用性。而STL 倡導泛型編程風格,即以通用的方式來編寫程序。STL采用C++模板機制實現了算法與數據類型的無關性。實際上,為了支持通用程序設計,STL實現了 算法與容 器(數據結構)的分離。這樣,同一算法適用於不同的容器和數據類型,成為通用性算法,可以最大限度地節省源代碼。因此STL比傳統的函數庫或類庫具有更好的代碼 重用性
  
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
/*******************************************
*        程序名:p10_9.cpp                    *
*  功  能:算法(algorithm)示例        *
*******************************************/
#include<iostream>
#include<algorithm>
#include<vector>
using namespace std;
 
template<class T>
void print(T &con)    //輸出容器中所有元素
{
  if(con.empty())
         cout<<"Container is empty!"<<endl;
  else
  {
  T::iterator it;   //設置迭代器
 
  for(it=con.begin(); it!=con.end();it++)
  {
cout<<*it<<" ";
      }
  cout<<endl;
  }
}

 

26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
int main()
{
  int num;
  vector<char> vec_A(8);  //定義容器vec_A
 
  cout<<"Fill vec_A with 'A':"<<endl; 
  fill(vec_A.begin(),vec_A.end(),'A');  //填充數據元素
  print(vec_A);
  cout<<"Copy element of vector to vec_A:"<<endl;
 
  char array_B[]={'B','B','B','B',};
  vector<char> vec_B(array_B,array_B+4);  //定義容器vec_A,並初始化
  copy(vec_B.begin(),vec_B.end(),vec_A.begin()+2);   //復制數據元素
  print(vec_A);
  cout<<"Remove 'A' from vec_A:"<<endl;
  vector<char> ::iterator it;
  it=remove(vec_A.begin(),vec_A.end(),'A');  //移除數據元素
  vec_A.erase(it,vec_A.end());               //刪除數據元素
  print(vec_A);
  cout<<"Repalce 'B' with 'C':"<<endl;
 
  replace(vec_A.begin(),vec_A.begin()+2,'B','C');  //替換數據元素
  replace(vec_B.begin(),vec_B.end(),'B','X');
  print(vec_A);

 

52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
  cout<<"Inserting:"<<endl;
  vec_A.insert(vec_A.begin(),'D');  // 插入數據元素
  vec_A.insert(vec_A.end(),'A');
  print(vec_A);
  cout<<"Sorting:"<<endl;
  sort(vec_A.begin(),vec_A.end());  // 排序
  print(vec_A);
 
  vector<char> vec_C(vec_A.size()+vec_B.size());
  cout<<"Merge vec_A and vec_B:"<<endl;
  merge(vec_A.begin(),vec_A.end(),vec_B.begin(),vec_B.end(),
  vec_C.begin());  // 合並
  print(vec_C);
  num=count(vec_C.begin(),vec_C.end(),'B');  // 統計數據元素
  cout<<"Counting the number of 'B' in vec_C:"<<endl;
  cout<<num<<endl;
  return 0;
}

 

類模板是能根據不同參數建立不同類型對象的類,類模板中的數據成員、成員
   函數的參數、成員函數的返回值可以取參數化類型。
類模板實例化是在建立對象時,根據傳入的參數類型,將類模板實例化成具
   體類,然后再建立對象。
棧是一種先進后出FILO(First In Last Out)的一種結構,在程序設計中廣
   泛使用棧,將棧設計成一個類模板,就可以在棧中存放任意類型的數據。
動態鏈表的插入與刪除節點的性能優於靜態數組,在程序設計中廣泛使用鏈
   表,將鏈表設計成一個類模板,就可以在鏈表節點中存放任意類型的數據。
STL(Standard Template Library)是C++提供的標准模板庫,它可以實現高
   效的泛型程序設計。
STL容器包括順序容器和關聯容器,利用容器適配器可以將順序容器轉換為新
   的容器。
在STL中,算法獨立於所操作的容器,利用已經定義的算法和迭代器,用戶可
   以方便靈活地地存取容器中存儲的各種數據元素。
在STL中,函數對象是由模板類產生的對象,函數對象在STL中被廣泛用作算
   法中子操作的參數,使算法變得更加通用。
 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM