日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程语言 > c/c++ >内容正文

c/c++

C++模板类详解

發布時間:2023/12/20 c/c++ 44 豆豆
生活随笔 收集整理的這篇文章主要介紹了 C++模板类详解 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.


一、模板類定義及實例化

1. 定義一個模板類:

template<class 模板參數表>class 類名{// 類定義......};

其中,template 是聲明模板類的關鍵字,表示聲明一個模板,模板參數可以是一個,也可以是多個,可以是類型參數 ,也可以是非類型參數。類型參數由關鍵字class或typename及其后面的標識符構成。非類型參數由一個普通參數構成,代表模板定義中的一個常量。

例:

template<class type,int width>//type為類型參數,width為非類型參數class Graphics;

注意:

(1)如果在全局域中聲明了與模板參數同名的變量,則該變量被隱藏掉。

(2)模板參數名不能被當作模板類定義中類成員的名字。

(3)同一個模板參數名在模板參數表中只能出現一次。

(4)在不同的模板類或聲明中,模板參數名可以被重復使用。

typedef string type;template<class type,int width>class Graphics{type node;//node不是string類型typedef double type;//錯誤:成員名不能與模板參數type同名};template<class type,class type>//錯誤:重復使用名為type的參數class Rect;template<class type> //參數名”type”在不同模板間可以重復使用class Round;


(5)
在模板類的前向聲明和定義中,模板參數的名字可以不同。

// 所有三個 Image 聲明都引用同一個類模板的聲明template <class T> class Image;template <class U> class Image;// 模板的真正定義template <class Type>class Image { //模板定義中只能引用名字”Type”,不能引用名字”T”和”U” };


(6)
類模板參數可以有缺省實參,給參數提供缺省實參的順序是先右后左。

template <class type, int size = 1024>class Image;template <class type=double, int size >//錯誤!class Image;


(7)
模板類名可以被用作一個類型指示符。當一個模板類名被用作另一個模板定義中的類型指示符時,必須指定完整的實參表

template<class type>class Graphics{Graphics *next;//在類模板自己的定義中不需指定完整模板參數表};template <class type>void show(Graphics<type> &g){Graphics<type> *pg=&g;//必須指定完整的模板參數表}


2.模板類實例化

定義:從通用的模板類定義中生成類的過程稱為模板實例化。

例:Graphics<int> gi;

模板類什么時候會被實例化呢?

當使用了模板類實例的名字,并且上下文環境要求存在類的定義時。

對象類型是一個模板類實例,當對象被定義時。此點被稱作類的實例化點

一個指針或引用指向一個模板類實例,當檢查這個指針或引用所指的對象時。

例:

template<class Type>class Graphics{};void f1(Graphics<char>);// 僅是一個函數聲明,不需實例化class Rect {Graphics<double>& rsd;// 聲明一個模板類引用,不需實例化Graphics<int> si;// si是一個Graphics類型的對象,需要實例化模板類}int main(){Graphcis<char>* sc;// 僅聲明一個模板類指針,不需實例化f1(*sc);//需要實例化,因為傳遞給函數f1的是一個Graphics<int>對象。int iobj=sizeof(Graphics<string>);//需要實例化,因為sizeof會計算Graphics<string>對象的大小,為了計算大小,編譯器必須根據模板類定義產生該類型。}

3.非類型參數的模板實參

要點

綁定給非類型參數的表達式必須是一個常量表達式。

從模板實參到非類型模板參數的類型之間允許進行一些轉換。包括左值轉換、限定修飾轉換、提升、整值轉換。

可以被用于非類型模板參數的模板實參的種類有一些限制。

例:

template<int* ptr> class Graphics{……};template<class Type,int size> class Rect{……};const int size=1024;Graphics<&size> bp1;//錯誤:從const int*->int*是錯誤的。Graphics<0> bp2;//錯誤不能通過隱式轉換把0轉換成指針值const double db=3.1415;Rect<double,db> fa1;//錯誤:不能將const double轉換成int.unsigned int fasize=255;Rect<String, fasize> fa2;//錯誤:非類型參數的實參必須是常量表達式,將unsigned改為const就正確。Int arr[10];Graphics<arr> gp;//正確

二、類模板的成員函數

要點:

類模板的成員函數可以在類模板的定義中定義(inline函數),也可以在類模板定義之外定義(此時成員函數定義前面必須加上template及模板參數)。

類模板成員函數本身也是一個模板,類模板被實例化時它并不自動被實例化,只有當它被調用或取地址,才被實例化。


Class Graphics{Graphics(){…}//成員函數定義在模板類的定義中void out();};template<class type>//成員函數定義在模板類定義之外void Graphics<type>::out(){…}

三、模板類的友元聲明

模板類中可以有三種友元聲明:

1.非模板友元類或友元函數

class Graphics{void out();};template<class T>Class Rect{friend class Graphics;//類Graphics、函數friend void create();// create、 out是類模板friend void Graphics::out();// Rect所有實例的友元};

2、綁定的友元模板類或函數模板。

3、非綁定的友元模板類或函數模板。

第二種聲明表示模板類的實例和它的友元之間是一種一對一的映射關系。

如圖:

第三種聲明表示模板類的實例和它的友元之間是一種一對多的映射關系。

如圖:

例:綁定的友元模板

template<class type>void create(Graphics<type>);template<class type>class Graphics{friend void create<type>(Graphics<type>);};

例:非綁定的友元模板

template<class type>class Graphics{template<class T>friend void create(Graphics<T>);};


注意:
當把非模板類或函數聲明為模板類友元時,它們不必在全局域中被聲明或定義,但將一個類的成員聲明為模板類友元,該類必須已經被定義,另外在聲明綁定的友元模板類或函數模板時,該模板也必須先聲明。

例:

template <class T>class A {private:friend class B<T>; //錯誤:類B必須先聲明};template <class T>class B{};

四、類模板的靜態數據成員、嵌套類型

1.類模板的靜態數據成員

要點:

靜態數據成員的模板定義必須出現在模板類定義之外。

模板類靜態數據成員本身就是一個模板,它的定義不會引起內存被分配,只有對其實例化才會分配內存。

當程序使用靜態數據成員時,它被實例化,每個靜態成員實例都與一個模板類實例相對應,靜態成員的實例引用要通過一個模板類實例。

例:

template<class type>class Graphics{static Graphics *next;static const type item;};template<class type>Graphics<type> * Graphics<type>::next=0;template<class type>type Graphics<type>::item=NULL;//靜態成員定義分為兩部分:前一部分是類型,比如Graphics<type>*,后一部分是名稱和值,比如Graphics<type>::next=0;

2.模板類的嵌套類型

要點:

在模板類中允許再嵌入模板,因此模板類的嵌套類也是一個模板,它可以使用外圍類模板的模板參數。

當外圍模板類被實例化時,它不會自動被實例化,只有當上下文需要它的完整類類型時,它才會被實例化。

公有嵌套類型可以被用在類定義之外,這時它的名字前必須加上模板類實例的名字。

例:

template<class type>class Graphics{public:template<class T>class Rect{void out(type a,T b);};};Graphics<int>::Rect<double> node;//引用公有嵌套類型必須加上模板類實例名字


五、成員模板

定義:成員定義前加上template及模板參數表。

要點:

在一個模板類中定義一個成員模板,意味著該模板類的一個實例包含了可能無限多個嵌套類和無限多個成員函數.

只有當成員模板被使用時,它才被實例化.

成員模板可以定義在其外圍類或模板類定義之外.

例:

</pre><pre class="cpp" name="code">template<class type>class Graphics<type>{public:template<class T>class Rect{void out(type a,T b);}; };template<class Gtype> template<class TT>void Graphics<Gtype>::Rect<TT>::out(Gtype a,TT b){}//成員模板被定義在模板類定義之外(要跟上完整模板實參)Graphics<int>的實例可能包括下列嵌套類型:Graphics<int>::Rect<double>Graphics<int>::Rect<string>

注意:模板類參數不一定與模板類定義中指定的名字相同。

?

六、模板類的編譯模式

1.包含編譯模式

這種編譯模式下,模板類的成員函數和靜態成員的定義必須被包含在“要將它們實例化”的所有文件中,如果一個成員函數被定義在模板類定義之外,那么這些定義應該被放在含有該模板類定義的頭文件中。

2.分離編譯模式

這種模式下,模板類定義和其inline成員函數定義被放在頭文件中,而非inline成員函數和靜態數據成員被放在程序文本文件中。

例:

</pre><pre class="cpp" name="code">//------Graphics.h---------export template<class type>Class Graphics{void Setup(const type &); };//-------Graphics.c------------#include “Graphics.h”template <class type>void Graphics<type>::Setup(const type &){…}//------user.c-----#include “Graphics.h”void main(){Graphics<int> *pg=new Graphics<int>;int ival=1;//Graphics<int>::Setup(const int &)的實例(下有注解)Pg->Setup(ival);}

Setup的成員定義在User.c中不可見,但在這個文件中仍可調用模板實例Graphics<int>::Setup(const int &)。為實現這一點,須將模板類聲明為可導出的:當它的成員函數實例或靜態數據成員實例被使用時,編譯器只要求模板的定義,它的聲明方式是在關鍵字template前加關鍵字export

3.顯式實例聲明

當使用包含編譯模式時,模板類成員的定義被包含在使用其實例的所有程序文本文件中,何時何地編譯器實例化模板類成員的定義,我們并不能精確地知曉,為解決這個問題,標準C++提供了顯式實例聲明:關鍵字template后面跟著關鍵字class以及模板類實例的名字。

例:

#include “Graphics.h”template class Graphics<int>;//顯式實例聲明


顯式實例化模板類時,它的所有成員也被顯式實例化。

?

七、模板類的特化及部分特化

1.模板類的特化

先看下面的例子:

template<class type>Class Graphics{public: void out(type figure){…}};Class Rect{…};


如果模板實參是Rect類型,我們不希望使用模板類Graphics的通用成員函數定義,來實例化成員函數out(),我們希望專門定義Graphics<Rect>::out()實例,讓它使用Rect里面的成員函數。

為此,我們可以通過一個顯示特化定義,為模板類實例的一個成員提供一個特化定義。

格式:template<> 成員函數特化定義

下面為模板類實例Graphics<Rect>的成員函數out()定義了顯式特化:

Template<> void Graphics<Rect>::out(Rect figure){…}

注意:

只有當通用模板類被聲明后,它的顯式特化才可以被定義。

若定義了一個模板類特化,則必須定義與這個特化相關的所有成員函數或靜態數據成員,此時模板類特化的成員定義不能以符號template<>作為打頭。(template<>被省略)

模板類不能夠在某些文件中根據通用模板定義被實例化,而在其他文件中卻針對同一組模板實參被特化。

2.模板類部分特化

如果模板有一個以上的模板參數,則有些人就可能希望為一個特定的模板實參或者一組模板實參特化類模板,而不是為所有的模板參數特化該類模板。即,希望提供這樣一個模板:它仍然是一個通用的模板,只不過某些模板參數已經被實際的類型或值取代。通過使用模板類部分特化,可以實現這一點。

例:

template<int hi,int wid>Class Graphics{…};template<int hi>//模板類的部分特化Class Graphics<hi,90>{…};


格式:template<模板參數表>

注意:

部分特化的模板參數表只列出模板實參仍然未知的那些參數。

模板類部分特化是被隱式實例化的。編譯器選擇“針對該實例而言最為特化的模板定義”進行實例化,當沒有特化可被使用時,才使用通用模板定義。

例:Graphics<24,90> figure;

它即能從通用模板類定義被實例化,也能從部分特化的定義被實例化,但編譯器選擇的是部分特化來實例化模板。

模板類部分特化必須有它自己對成員函數、靜態數據成員和嵌套類的定義。

?

八、名字空間和模板類

模板類定義也可以被放在名字空間中。例如:

Namespace cplusplus_primer{template<class type>Class Graphics{…};template<class type>type create(){…}}

當模板類名字Graphics被用在名字空間之外時,它必須被名字空間名cplusplus_primer限定修飾,或者通過一個using聲明或指示符被引入。例如:

Void main(){using cplusplus_primer::Graphics;Graphics<int> *pg=new Graphics<int>;}

注意:在名字空間中聲明類模板也會影響該模板類及其成員的特化和部分特化聲明的方式,模板類或模板類成員的特化聲明必須被聲明在定義通用模板的名字空間中(可以在名字空間之外定義模板特化)。

一個關于隊列的例子,下面將其代碼整理如下:

#include "iostream.h"template <class Type> class QueueItem;template <class Type>class Queue {public:friend ostream& operator<<(ostream &os,const Queue<Type> &q);Queue() : front( 0 ), back ( 0 ) { }~Queue(){}void add( const Type & );bool is_empty() const{return front == 0;}Type remove();private:QueueItem<Type> *front;QueueItem<Type> *back;};template <class Type>class QueueItem{public:QueueItem(Type val){item=val;next=0;}friend class Queue<Type>;friend ostream& operator<<(ostream &os,const Queue<Type> &q);friend ostream& operator<<(ostream &os,const QueueItem<Type> &qi);private:Type item;QueueItem *next;};template <class Type>void Queue<Type>::add(const Type &val){QueueItem<Type> *pt =new QueueItem<Type>(val);if ( is_empty() )front = back = pt;else{back->next = pt;back = pt;}}template <class Type>Type Queue<Type>::remove(){if ( is_empty() ){cerr << "remove() on empty queue \n";exit(-1);}QueueItem<Type> *pt = front;front = front->next;Type retval = pt->item;delete pt;return retval;}template <class Type>ostream& operator<<(ostream &os, const Queue<Type> &q) //輸出隊列成員{os << "< ";QueueItem<Type> *p;for ( p = q.front; p; p = p->next )os << *p << “ ;//用到了Queue和QueueItem的私有成員,因此需將此運算符重//載函數聲明為Queue和QueueItem的友元,書上沒有將此函數聲明為QueueItemos << “ >”;//的友元。return os;}template <class Type>ostream& operator<< ( ostream &os, const QueueItem<Type> &qi ){os << qi.item;//用到了QueueItem的私有成員,因此需將此運算符重載函數聲明//為QueueItem的友元return os;}void main(){Queue<int> qi;cout << qi << endl;int ival;for ( ival = 0; ival < 10; ++ival )qi.add( ival );cout << qi << endl;int err_cnt = 0;for ( ival = 0; ival < 10; ++ival ) {int qval = qi.remove();if ( ival != qval ) err_cnt++;}cout << qi << endl;if ( !err_cnt )cout << "!! queue executed ok\n";else cout << “?? queue errors: " << err_cnt << endl;}


運行結果


作者:Out Man
出處:http://www.cnblogs.com/assemble8086/
本文版權歸作者和博客園共有,歡迎轉載,但未經作者同意必須保留作者信息,且在文章頁面明顯位置給出原文連接。

 

總結

以上是生活随笔為你收集整理的C++模板类详解的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。

主站蜘蛛池模板: 毛片一级在线观看 | 国产精品久久一区二区三区 | 麻豆偷拍 | 中文字幕在线资源 | 91久久国语露脸精品国产高跟 | 毛片网络 | 性欧美日本| 僵尸叔叔在线观看国语高清免费观看 | 亚洲综合色在线观看 | 国产精品888 | 黄色一级片久久 | 长腿校花无力呻吟娇喘的视频 | 亚洲区在线播放 | 阿的白色内裤hd中文 | 亚洲啊v| 精品一区二区三区四区五区 | 成人一区二区免费视频 | 日本a天堂| 在线99热 | 日韩精品在线免费观看视频 | 性活交片大全免费看 | 性chinese天美传媒麻 | 亚洲人成7777| 永久免费在线观看视频 | 青青草原亚洲 | 久久久精品电影 | 欧美日韩国产一级 | 黄色成人免费观看 | 久久久久国产精品区片区无码 | 久久精品电影网 | 少妇裸体视频 | 尤果网福利视频在线观看 | 色综合久久综合 | 一级黄色片一级黄色片 | 精品人妻久久久久一区二区三区 | 99ri在线| 欧美在线观看a | 欧美卡一卡二卡三 | 一卡二卡在线视频 | 欧美一级激情 | 91成人国产 | 五月在线 | 日韩人妻精品在线 | 精品人妻一区二区三区久久 | av中文字幕第一页 | 国产无遮挡又黄又爽免费视频 | 免费一级一片 | 亚洲精选国产 | 亚洲无码精品免费 | 亚洲精品中文字幕乱码无线 | www.av麻豆 | 欧美成人做爰猛烈床戏 | 91制服诱惑 | 美女少妇毛片 | xxxxx黄色 | 久久久久国产精品区片区无码 | v片在线观看 | 喷潮在线| 人妻换人妻仑乱 | 午夜激情视频 | 色欲av无码精品一区 | 第一章豪妇荡乳黄淑珍 | 高清国产一区二区三区 | 久久久国产精品一区二区三区 | 国产激情无码一区二区三区 | 免费看日韩 | 亚欧洲精品在线视频 | 簧片av| 亚洲精品一二三四 | 99热国产在线观看 | 影音先锋在线看 | 国产一卡二卡在线播放 | 黄色网在线播放 | 国产一区二区内射 | 国产女人18毛片水真多18精品 | 国产乱码精品一区二区三区不卡 | 91黄色免费网站 | 国产精品久久..4399 | 亚洲黄色免费在线观看 | 亚洲欧美伊人 | 大肉大捧一进一出好爽 | 午夜男人天堂 | 欧美国产二区 | 91久久网| 成人免费毛片男人用品 | 尤物网站在线观看 | 在线你懂得 | 日日拍夜夜拍 | 99久久综合网 | 美腿丝袜一区二区三区 | 亚洲精品视频在线观看免费 | 视频在线观看91 | 久久精品欧美一区二区 | 亚州av网站 | 激情视频网址 | 最近中文字幕在线中文视频 | 国产精品久久久久久免费观看 | 天堂中文网在线 | 久久婷五月 |