欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

C++函數(shù)模板與類(lèi)模板實(shí)例解析

 更新時(shí)間:2014年08月14日 17:58:38   投稿:shichen2014  
這篇文章主要介紹了C++函數(shù)模板與類(lèi)模板,需要的朋友可以參考下

本文針對(duì)C++函數(shù)模板與類(lèi)模板進(jìn)行了較為詳盡的實(shí)例解析,有助于幫助讀者加深對(duì)C++函數(shù)模板與類(lèi)模板的理解。具體內(nèi)容如下:

泛型編程(Generic Programming)是一種編程范式,通過(guò)將類(lèi)型參數(shù)化來(lái)實(shí)現(xiàn)在同一份代碼上操作多種數(shù)據(jù)類(lèi)型,泛型是一般化并可重復(fù)使用的意思。泛型編程最初誕生于C++中,目的是為了實(shí)現(xiàn)C++的STL(標(biāo)準(zhǔn)模板庫(kù))。

模板(template)是泛型編程的基礎(chǔ),一個(gè)模板就是一個(gè)創(chuàng)建類(lèi)或函數(shù)的藍(lán)圖或公式。例如,當(dāng)使用一個(gè)vector這樣的泛型類(lèi)型或者find這樣的泛型函數(shù)時(shí),我們提供足夠的信息,將藍(lán)圖轉(zhuǎn)換為特定的類(lèi)或函數(shù)。

一、函數(shù)模板

一個(gè)通用的函數(shù)模板(function template)就是一個(gè)公式,可用來(lái)生成針對(duì)特定類(lèi)型或特定值的函數(shù)版本。模板定義以關(guān)鍵字template開(kāi)始,后面跟一個(gè)模板參數(shù)列表,列表中的多個(gè)模板參數(shù)(template parameter)以逗號(hào)分隔。模板參數(shù)表示在類(lèi)或函數(shù)定義中用到的類(lèi)型或值。

1、類(lèi)型參數(shù)

一個(gè)模板類(lèi)型參數(shù)(type parameter)表示的是一種類(lèi)型。我們可以將類(lèi)型參數(shù)看作類(lèi)型說(shuō)明符,就像內(nèi)置類(lèi)型或類(lèi)類(lèi)型說(shuō)明符一樣使用。類(lèi)型參數(shù)前必須使用關(guān)鍵字class 或typename:

template <typename T> // typename和class一樣的 
T function(T* p) 
{ 
  T tmp = *p;  // 臨時(shí)變量類(lèi)型為T(mén) 
  //... 
  return tmp;  // 返回值類(lèi)型為T(mén) 
} 

關(guān)鍵字typename和class是一樣的作用,但顯然typename比class更為直觀,它更清楚地指出隨后的名字是一個(gè)類(lèi)型名。

編譯器用模板類(lèi)型實(shí)參為我們實(shí)例化(instantiate)特定版本的函數(shù),一個(gè)版本稱做模板的一個(gè)實(shí)例(instantiation)。當(dāng)我們調(diào)用一個(gè)函數(shù)模板時(shí),編譯器通常用函數(shù)實(shí)參來(lái)為我們推斷模板實(shí)參。當(dāng)然如果函數(shù)沒(méi)有模板類(lèi)型的參數(shù),則我們需要特別指出來(lái):

int a = 10; 
cout << function(&a) << endl;   // 編譯器根據(jù)函數(shù)實(shí)參推斷模板實(shí)參 
 
cout << function<int>(&a) << endl;  // <int>指出模板參數(shù)為int 

2、非類(lèi)型參數(shù)

在模板中還可以定義非類(lèi)型參數(shù)(nontype parameter),一個(gè)非類(lèi)型參數(shù)表示一個(gè)值而非一個(gè)類(lèi)型。我們通過(guò)一個(gè)特定的類(lèi)型名而非關(guān)鍵字class或typename來(lái)指定非類(lèi)型參數(shù):

// 整形模板 
template<unsigned M, unsigned N> 
void add() 
{ 
  cout<< M+N << endl; 
} 
 
// 指針 
template<const char* C> 
void func1(const char* str) 
{ 
  cout << C << " " << str << endl; 
} 
 
// 引用 
template<char (&R)[9]> 
void func2(const char* str) 
{ 
  cout << R << " " << str << endl; 
} 
 
// 函數(shù)指針 
template<void (*f)(const char*)> 
void func3(const char* c) 
{ 
  f(c); 
} 
 
void print(const char* c) { cout << c << endl;} 
 
char arr[9] = "template";  // 全局變量,具有靜態(tài)生存期 
 
int main() 
{ 
  add<10, 20>(); 
  func1<arr>("pointer"); 
  func2<arr>("reference"); 
  func3<print>("template function pointer"); 
  return 0; 
} 

當(dāng)實(shí)例化時(shí),非類(lèi)型參數(shù)被一個(gè)用戶提供的或編譯器推斷出的值所替代。一個(gè)非類(lèi)型參數(shù)可以是一個(gè)整型,或者是一個(gè)指向?qū)ο蠡蚝瘮?shù)的指針或引用:綁定到整形(非類(lèi)型參數(shù))的實(shí)參必須是一個(gè)常量表達(dá)式,綁定到指針或引用(非類(lèi)型參數(shù))的實(shí)參必須具有靜態(tài)的生存期(比如全局變量),不能把普通局部變量 或動(dòng)態(tài)對(duì)象綁定到指針或引用的非類(lèi)型形參。

二、類(lèi)模板

相應(yīng)的,類(lèi)模板(class template)是用來(lái)生成類(lèi)的藍(lán)圖。與函數(shù)模板的不同之處是,編譯器不能為類(lèi)模板推斷模板參數(shù)類(lèi)型,所以我們必須顯式的提供模板實(shí)參。與函數(shù)模板一樣,類(lèi)模板參數(shù)可以是類(lèi)型參數(shù),也可以是非類(lèi)型參數(shù),這里就不再贅述了。

template<typename T> 
class Array { 
public: 
  Array(T arr[], int s); 
  void print(); 
private: 
  T *ptr; 
  int size; 
}; 
 
// 類(lèi)模板外部定義成員函數(shù) 
template<typename T> 
Array<T>::Array(T arr[], int s) 
{ 
  ptr = new T[s]; 
  size = s; 
  for(int i=0; i<size; ++i) 
    ptr[i]=arr[i]; 
} 
 
template<typename T> 
void Array<T>::print() 
{ 
  for(int i=0; i<size; ++i) 
    cout << " " << *(ptr+i); 
  cout << endl; 
} 
 
int main() 
{ 
  char a[5] = {'J','a','m','e','s'}; 
  Array<char> charArr(a, 5); 
  charArr.print(); 
 
  int b[5] = { 1, 2, 3, 4, 5}; 
  Array<int> intArr(b, 5); 
  intArr.print(); 
 
  return 0; 
}

類(lèi)模板的成員函數(shù)

與其他類(lèi)一樣,我們既可以在類(lèi)模板內(nèi)部,也可以在類(lèi)模板外部定義其成員函數(shù)。定義在類(lèi)模板之外的成員函數(shù)必須以關(guān)鍵字template開(kāi)始,后接類(lèi)模板參數(shù)列表。

template <typename T> 
return_type class_name<T>::member_name(parm-list) { } 

默認(rèn)情況下,對(duì)于一個(gè)實(shí)例化了的類(lèi)模板,其成員函數(shù)只有在使用時(shí)才被實(shí)例化。如果一個(gè)成員函數(shù)沒(méi)有被使用,則它不會(huì)被實(shí)例化。

類(lèi)模板和友元

當(dāng)一個(gè)類(lèi)包含一個(gè)友元聲明時(shí),類(lèi)與友元各自是否是模板是相互無(wú)關(guān)的。如果一個(gè)類(lèi)模板包含一個(gè)非模板的友元,則友元被授權(quán)可以訪問(wèn)所有模板的實(shí)例。如果友元自身是模板,類(lèi)可以授權(quán)給所有友元模板的實(shí)例,也可以只授權(quán)給特定實(shí)例。

// 前置聲明,在將模板的一個(gè)特定實(shí)例聲明為友元時(shí)要用到 
template<typename T> class Pal; 
 
// 普通類(lèi) 
class C { 
  friend class Pal<C>; // 用類(lèi)C實(shí)例化的Pal是C的一個(gè)友元 
  template<typename T> friend class Pal2; //Pal2所有實(shí)例都是C的友元;無(wú)須前置聲明 
}; 
 
// 模板類(lèi) 
template<typename T> class C2 { 
  // C2的每個(gè)實(shí)例將用相同類(lèi)型實(shí)例化的Pal聲明為友元,一對(duì)一關(guān)系 
  friend class Pal<T>; 
  // Pal2的所有實(shí)例都是C2的每個(gè)實(shí)例的友元,不需要前置聲明 
  template<typename X> friend class Pal2;  
  // Pal3是普通非模板類(lèi),它是C2所有實(shí)例的友元 
  friend class Pal3; 
}; 

類(lèi)模板的static成員

類(lèi)模板可以聲明static成員。類(lèi)模板的每一個(gè)實(shí)例都有其自己獨(dú)有的static成員對(duì)象,對(duì)于給定的類(lèi)型X,所有class_name<X>類(lèi)型的對(duì)象共享相同的一份static成員實(shí)例。

template<typename T> 
class Foo { 
public: 
  void print(); 
  //...其他操作 
private: 
  static int i; 
}; 
 
template<typename T> 
void Foo<T>::print() 
{ 
  cout << ++i << endl; 
} 
 
template<typename T> 
int Foo<T>::i = 10; // 初始化為10 
 
int main() 
{ 
  Foo<int> f1; 
  Foo<int> f2; 
  Foo<float> f3; 
  f1.print();  // 輸出11 
  f2.print();  // 輸出12 
  f3.print();  // 輸出11 
  return 0; 
}

我們可以通過(guò)類(lèi)類(lèi)型對(duì)象來(lái)訪問(wèn)一個(gè)類(lèi)模板的static對(duì)象,也可以使用作用域運(yùn)算符(::)直接訪問(wèn)靜態(tài)成員。類(lèi)似模板類(lèi)的其他成員函數(shù),一個(gè)static成員函數(shù)也只有在使用時(shí)才會(huì)實(shí)例化。

相關(guān)文章

  • C++實(shí)現(xiàn)Window環(huán)境聊天室功能

    C++實(shí)現(xiàn)Window環(huán)境聊天室功能

    這篇文章主要為大家詳細(xì)介紹了C++實(shí)現(xiàn)Window環(huán)境聊天室功能,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2021-06-06
  • c++中的內(nèi)聯(lián)函數(shù)inline用法實(shí)例

    c++中的內(nèi)聯(lián)函數(shù)inline用法實(shí)例

    在本篇文章里小編給大家整理的是關(guān)于c++中的內(nèi)聯(lián)函數(shù)inline用法實(shí)例以及相關(guān)知識(shí)點(diǎn),有需要的朋友們學(xué)習(xí)下。
    2019-09-09
  • C++中new的用法及說(shuō)明

    C++中new的用法及說(shuō)明

    這篇文章主要介紹了C++中new的用法及說(shuō)明,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2022-11-11
  • 深入C中常用的三種排序方法總結(jié)以及探討分析

    深入C中常用的三種排序方法總結(jié)以及探討分析

    本篇文章是對(duì)C中常用的三種排序方法總結(jié)以及探討分析的概述,需要的朋友參考下
    2013-05-05
  • Qt編譯OpenCV的實(shí)現(xiàn)步驟

    Qt編譯OpenCV的實(shí)現(xiàn)步驟

    本文主要介紹了Qt編譯OpenCV的實(shí)現(xiàn)步驟,通過(guò)詳細(xì)的步驟和說(shuō)明,幫助開(kāi)發(fā)者在Qt環(huán)境中成功集成并編譯OpenCV,從而為各類(lèi)計(jì)算機(jī)視覺(jué)項(xiàng)目提供強(qiáng)大的支持,感興趣的可以了解一下
    2024-01-01
  • C++如何實(shí)現(xiàn)二叉樹(shù)鏈表

    C++如何實(shí)現(xiàn)二叉樹(shù)鏈表

    這篇文章主要介紹了C++如何實(shí)現(xiàn)二叉樹(shù)鏈表,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2022-07-07
  • 一般函數(shù)指針和類(lèi)的成員函數(shù)指針深入解析

    一般函數(shù)指針和類(lèi)的成員函數(shù)指針深入解析

    以下是對(duì)一般函數(shù)指針和類(lèi)的成員函數(shù)指針進(jìn)行了介紹。需要的朋友可以過(guò)來(lái)參考下
    2013-08-08
  • 一文總結(jié)C++中的異常

    一文總結(jié)C++中的異常

    異常是一種處理錯(cuò)誤的方式,當(dāng)一個(gè)函數(shù)發(fā)現(xiàn)自己無(wú)法處理的錯(cuò)誤時(shí)就可以拋出異常,讓函數(shù)的直接或間接調(diào)用者處理這個(gè)錯(cuò)誤,本文給大家總結(jié)了C++中的異常,需要的朋友可以參考下
    2023-10-10
  • C語(yǔ)言實(shí)現(xiàn)車(chē)輛信息管理系統(tǒng)

    C語(yǔ)言實(shí)現(xiàn)車(chē)輛信息管理系統(tǒng)

    這篇文章主要為大家詳細(xì)介紹了C語(yǔ)言實(shí)現(xiàn)車(chē)輛信息管理系統(tǒng),文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2022-03-03
  • C++實(shí)現(xiàn)浮點(diǎn)數(shù)精確加法

    C++實(shí)現(xiàn)浮點(diǎn)數(shù)精確加法

    這篇文章主要為大家詳細(xì)介紹了C++實(shí)現(xiàn)浮點(diǎn)數(shù)精確加法,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2020-05-05

最新評(píng)論