相信寫過Java的童鞋們都知道泛型編程,在C++中與之對應的就是模板。
模板是一種對類型進行參數化的工具,通常有兩種形式:函數模板和類模板。
模板是一些為多種類型而編寫的函數和類,而且這些類型都沒有指定。當使用模板的時候,你只需要把所希望的類型作為一個(顯式或者隱式的)實參傳遞給模板。 另外,由于模板是語言本身所具有的特性,所以它完全支持類型檢查和作用域。使用模板的目的就是能夠讓程序員編寫與類型無關的代碼,盡可能地減少重復代碼。
眾所周知,C++是一門強類型的靜態語言。在聲明變量、函數和大多數其他類型的實體的時候,C++要求我們使用指定的類型。 然而,對于許多代碼,除了類型不同之外,其余的代碼看起來都是相同的。例如我們需要實現一個交換兩個變量的函數,為了通用性, 這個交換變量的函數不能固定兩個變量的類型,這就使得模版橫空出世。。。
在C++標準庫中,幾乎所有的代碼都是模板代碼,可以說沒有C++模板就沒有STL。
首先我們看下函數模板的格式:
template <typename 形參名,typename 形參名,......> 返回類型 函數名(參數列表){ 函數體}
或者使用class關鍵字也可:
template <class 形參名,class 形參名,......> 返回類型 函數名(參數列表){ 函數體}
為什么會有兩種不同的格式呢?這是因為鑒于歷史的原因,你可能還會使用class取代typename,來定義類型參數。 在C++語言的演化過程中,關鍵字typename的出現相對較晚一些;在它之前,關鍵字class是引入類型參數的唯一方式,并一直作為有效方式保留下來。 但是更加標準的格式是使用typename關鍵字。
例如我們使用模板定義了返回較大值的模板函數:
template <typename T>const T& max_fun(const T& a,const T& b){ return a >= b? a:b;}
下面我們調用一下我們定義的模板函數max_fun:
int main(int argc, char* argv[]) { // 都是int類型 ok int max = max_fun(10,10); // 都是double類型 ok int max = max_fun(10,10); // 一個int類型,一個double類型 編譯不通過 int max = max_fun(10,11.0); std::cout << "max:" << max << std::endl; return 0;}
在上面的例子中我們發現函數max_fun(10,11.0)報錯了,無法編譯通過,這是為什么呢?因為我們定義的模板函數max_fun只有一個參數類型, 但是max_fun(10,11.0)卻傳了兩個不同的參數類型,二載函數模板中是不允許進行自動類型轉換的,因此報錯,有兩種方式可以解決這個報錯:
max_fun(10,static_cast<int>(11.0));
max_fun<int>(10,11.0);
重點:在函數模板實參演繹的過程中,是不允許進行自動類型轉換的。
模板函數在使用時編譯器回自動實現實例化,只要使用函數模板,(編譯器)會自動地引發這樣一個實例化過程,因此程序員并不需要額外地請求模板的實例化。
和普通函數一樣,函數模板也可以被重載。就是說,相同的函數名稱可以根據不同的函數參數具有不同的函數定義; 于是,當使用函數名稱進行函數調用的時候,C++編譯器必須決定究竟要調用哪個候選函數。
一個非模板函數可以和一個同名的函數模板同時存在,而且該函數模板還可以被實例化為這個非模板函數。 對于非模板函數和同名的函數模板,如果其他條件都是相同的話,那么在調用的時候,重載解析過程通常會調用非模板函數,而不會從該模板產生出一個實例。
下面我們通過一個小例子來了解下重載函數模板:
#include <iostream>#include <memory>template <typename T>const T& max_fun(const T& a,const T& b){std::cout << "模板類型max_fun:"<< std::endl;return a >= b? a:b;}const int& max_fun(const int& a,const int& b){std::cout << "int 類型max_fun:"<< std::endl;return a >= b? a:b;}int main(int argc, char* argv[]) {// 都是double類型 匹配到模板函數max_fun// int max = max_fun(10.0,11.0);// 都是int類型 匹配到 普通函數max_fun// int max = max_fun(10,10);// 一個char類型,一個double類型 匹配到普通函數max_funint max = max_fun('a',11.0);std::cout << "max:" << max << std::endl;return 0;}
在上面的例子main函數中我們多次調用了函數max_fun,那么怎么區分是調用了模板函數max_fun還是調用了重載的普通函數max_fun呢?
有一條規則是這樣的:
一個非模板函數可以和一個同名的函數模板同時存在,而且該函數模板還可以被實例化為這個非模板函數。對于非模板函數和同名的函數模板,如果其他條件都是相同的話,那么在調用的時候,重載解析過程通常會調用非模板函數,而不會從該模板產生出一個實例。
因此在上面的例子中我們可以很容易地看出第17行調用的是模板函數max_fun,因為沒有參數是double類型的max_fun被重載。 但在第19行因為有一個參數是int類型的重載函數max_fun,因此這一行調用的是普通重載函數max_fun。
那么在第21行也是調用了int類型的重載函數max_fun,這是為什么呢?
這是因為模板是不允許自動類型轉化的,但普通函數可以進行自動類型轉換,所以第21行調用的是int類型的重載函數max_fun(‘a’和11.0都被轉化為int)。
函數重載應該牢記一條首要規則:函數的所有重載版本的聲明都應該位于該函數被調用的位置之前。
本文鏈接:http://www.www897cc.com/showinfo-26-44395-0.htmlC++之函數模板
聲明:本網頁內容旨在傳播知識,若有侵權等問題請及時與本網聯系,我們將在第一時間刪除處理。郵件:2376512515@qq.com