[導(dǎo)讀] 最近使用C++做些編程,把日常遇到的些比較重要的概念總結(jié)分享一下。本文來分享一下模板類的原理,以及為什么需要模板類,使用時的基本要點(diǎn)。
為什么需要模板
比如需要設(shè)計(jì)一個描述點(diǎn)的類,大致很快可以寫成這樣:
class Point_F { public: /*默認(rèn)傳入參數(shù)為0,0*/ Point_F(float x0 = 0, float y0 = 0) :x(x0), y(y0) /*初始化列表*/ { } /*用const修飾函數(shù),表示函數(shù)不會修改成員數(shù)據(jù)*/ float get_x() const { return x; } float get_y() const { return y; } private: /*一般會將數(shù)據(jù)放在私有區(qū),以對外隱藏*/ float x; float y; };
可問題是,在有的場合這點(diǎn)的坐標(biāo)系有可能不需要浮點(diǎn),比如界面設(shè)計(jì)中點(diǎn)往往是整型表示即可,那此時就需要再設(shè)計(jì)一個整型成員類:
class Point_I { public: /*默認(rèn)傳入?yún)?shù)為0,0*/ Point_f(int x0 = 0, int y0 = 0) :x(x0), y(y0) /*初始化列表*/ { } /*用const修飾函數(shù),表示函數(shù)不會修改成員數(shù)據(jù)*/ int get_x() const { return x; } int get_y() const { return y; } private: /*一般會將數(shù)據(jù)放在私有區(qū),以對外隱藏*/ int x; int y; };
可是在應(yīng)用代碼中,往往發(fā)現(xiàn)對于不同數(shù)據(jù)成員的應(yīng)用操作確實(shí)基本類似,而且應(yīng)用代碼往往這兩種(甚至更多成員數(shù)據(jù)類型)都可能會同時用到,僅僅因?yàn)閿?shù)據(jù)類型就需要笨笨的將原代碼在改寫一下,在現(xiàn)代高級語言中,這顯然就比較機(jī)械了。
C++中有沒有可能將不同成員數(shù)據(jù)類型但是其頂層邏輯相同的對象,設(shè)計(jì)為一個類呢?就比如:
C++模板編程正是為了解決這樣的需求而設(shè)計(jì)的機(jī)制。該機(jī)制允許函數(shù)或類使用泛型類型(generic type)進(jìn)行操作。從而,函數(shù)或類就可以處理許多不同的數(shù)據(jù)類型,而無需為每種數(shù)據(jù)類型重寫相應(yīng)的類或者函數(shù)。
怎么實(shí)現(xiàn)的呢?
這里又可以大致分這樣三種情況:
類模板(Class templates)
**成員模板(Member templates) **
函數(shù)模板
函數(shù)模板其基本語法范式為:
template 《class identifier》 function_declaration; template 《typename identifier》 function_declaration;
template 為模板關(guān)鍵字
《typename identifier》 、《class identifier》 定義函數(shù)參數(shù)泛型類型或函數(shù)體類變量泛型類型
比如:
#include 《iostream》 using namespace std; template 《typename T》 T max(T a, T b) { return a 》 b ? a : b ; }
又或者寫成如下形式:
#include 《iostream》 using namespace std; template 《class T》 T max(T a, T b) { return a 》 b ? a : b ; }
那么或許有的朋友會任務(wù)關(guān)鍵字class就意味著自定義類,而typename則是基本數(shù)據(jù)類型,比如int,float等,這樣理解其實(shí)是不對的,從C++編譯器的角度template 《typename T》與template 《class T》其語義是一樣的,都是泛型,用戶在使用這個模板函數(shù)的時候,所傳入的參數(shù)都既可以是基本數(shù)據(jù)類型,也可以是類名。
對于上面的代碼,或許初使用的朋友還會問,是不是可以隨便傳入類,這有可能編譯不過。為什么呢?你傳入的類需要支持》操作符,如果對于某個類你想使用該函數(shù),而本身不支持》操作符,則需要實(shí)現(xiàn)》操作符。
類模板
與函數(shù)模板類似,類內(nèi)部成員數(shù)據(jù)或者函數(shù)的參數(shù)或變量會使用,模板關(guān)鍵字定義的泛型名。比如:
template 《typename T》 class Point_T { public: Point_T(T x0 = 0, T y0 = 0) :x(x0), y(y0) { } T get_x() const { return x; } T get_y() const { return y; } private: T x; T y; };
這小段代碼就回答了之前提出的問題,可以支持不同數(shù)據(jù)類型的點(diǎn)。
int main() { Point_T《int》 p1(1, 2); Point_T《float》 p2(1.1f, 2.2f); cout 《《 p1.get_x() 《《 endl 《《 p1.get_y() 《《 endl; cout 《《 p2.get_x() 《《 endl 《《 p2.get_y() 《《 endl; }
以上述簡單例子看,分別構(gòu)造了整型點(diǎn)p1,以及浮點(diǎn)型點(diǎn)p2,那么究竟怎么做到的呢?為了理解得更清楚,這里將其關(guān)鍵匯編代碼段拷貝下來簡要看看:
Point_T《int》 p1(1, 2); 000C1D6C push 2 000C1D6E push 1 000C1D70 lea ecx,[p1] 000C1D73 call Point_T《int》::Point_T《int》 (0C11D1h) Point_T《float》 p2(1.1f, 2.2f); 000C1D78 push ecx 000C1D79 movss xmm0,dword ptr [__real@400ccccd (0C7B34h)] 000C1D81 movss dword ptr [esp],xmm0 000C1D86 push ecx 000C1D87 movss xmm0,dword ptr [__real@3f8ccccd (0C7B30h)] 000C1D8F movss dword ptr [esp],xmm0 000C1D94 lea ecx,[p2] 000C1D97 call Point_T《float》::Point_T《float》 (0C1064h)
可見編譯器對不同類型參數(shù)實(shí)際上做了相應(yīng)解析,相當(dāng)于根據(jù)用戶程序傳入的參數(shù)編譯出相應(yīng)的多份代碼。所以可以簡單理解成編譯器根據(jù)不同泛型實(shí)際參數(shù)類型生成了相應(yīng)的處理代碼。而前面所說的模板函數(shù)其原理也基本類似。
總結(jié)一下
通過些簡單例子,梳理一下模板函數(shù)以及模板類的基本概念以及原理,理解了這兩個概念,就比較容易理解成員模板。所謂泛型模板編程,其本質(zhì)是編譯器針對不同參數(shù)類型解析解析生成相應(yīng)的處理代碼。學(xué)會使用模板泛型編程你會發(fā)現(xiàn)你會少寫很多代碼,代碼看起來會比較優(yōu)雅,而其實(shí)操作起來也沒有想象中那么難。
編輯:jq
-
編程
+關(guān)注
關(guān)注
88文章
3637瀏覽量
93989 -
函數(shù)
+關(guān)注
關(guān)注
3文章
4346瀏覽量
62979 -
C++
+關(guān)注
關(guān)注
22文章
2114瀏覽量
73859 -
編譯器
+關(guān)注
關(guān)注
1文章
1642瀏覽量
49291
原文標(biāo)題:什么是函數(shù)模板、類模板?怎么做到的?
文章出處:【微信號:zhuyandz,微信公眾號:FPGA之家】歡迎添加關(guān)注!文章轉(zhuǎn)載請注明出處。
發(fā)布評論請先 登錄
相關(guān)推薦
如何用VSCODE創(chuàng)建一個LE5010的工程模板
圖紙模板中的文本變量
![圖紙<b class='flag-5'>模板</b>中的文本變量](https://file1.elecfans.com//web1/M00/F4/D5/wKgZoWcy18-AG-szAAJXO8IiHgQ099.png)
A0到A4的圖框只要一個圖紙模板就搞定了?
![A0到A4的圖框只要一個圖紙<b class='flag-5'>模板</b>就搞定了?](https://file1.elecfans.com//web1/M00/F4/D5/wKgZoWcy19eAF0ZLAABXGSxO4uM322.png)
摩爾線程開源高性能線性代數(shù)模板庫MUTLASS
手寫圖像模板匹配算法在OpenCV中的實(shí)現(xiàn)
![手寫圖像<b class='flag-5'>模板</b>匹配算法在OpenCV中的實(shí)現(xiàn)](https://file1.elecfans.com/web1/M00/F4/B4/wKgZoWcxaGqAPU4YAAAPQhF4fVs669.png)
使用C語言實(shí)現(xiàn)函數(shù)模板
使用helloword的模板,上傳了IG502但不能運(yùn)行,為什么?
如何使用Vitis自帶的LWIP模板進(jìn)行PS端千兆以太網(wǎng)TCP通信?
![如何使用Vitis自帶的LWIP<b class='flag-5'>模板</b>進(jìn)行PS端千兆以太網(wǎng)TCP通信?](https://file1.elecfans.com/web2/M00/DE/26/wKgZomYtuKiABLnnAAA3l3ALMRU080.png)
CW32F003E4芯片入門學(xué)習(xí):4.工程模板創(chuàng)建(使用例程或模板)
![CW32F003E4芯片入門學(xué)習(xí):4.工程<b class='flag-5'>模板</b>創(chuàng)建(使用例程或<b class='flag-5'>模板</b>)](https://file1.elecfans.com/web2/M00/D8/89/wKgaomYoo4-AVNdoAAAZr-vr_2o883.png)
電源模塊測試數(shù)據(jù)一鍵導(dǎo)出,自定義報(bào)告模板
微軟Visio網(wǎng)頁版新增八個可定制思維導(dǎo)圖模板
TouchGFX的Application Templates模板里面為什么只有2個?
Altium Designer與Gerber模板的導(dǎo)入指南
![Altium Designer與Gerber<b class='flag-5'>模板</b>的導(dǎo)入指南](https://file1.elecfans.com/web2/M00/C6/EE/wKgaomYEy1-AcFHrAABS2OuWoC4414.png)
CW32F003E4芯片入門學(xué)習(xí):4.工程模板創(chuàng)建(使用例程或模板)
![CW32F003E4芯片入門學(xué)習(xí):4.工程<b class='flag-5'>模板</b>創(chuàng)建(使用例程或<b class='flag-5'>模板</b>)](https://file1.elecfans.com/web2/M00/C5/E1/wKgZomYDeIuAHSLzAABPS9RmuM4659.jpg)
評論