C++中的模板類(lèi)&模板函數(shù)
C++模板類(lèi)&模板函數(shù)
模板類(lèi)
模板類(lèi)的定義使用 template<typename T>
或 template<class T>
,將具有相同功能的代碼合并,增加代碼的簡(jiǎn)潔性和易讀性。
例如在計(jì)算凸包的例子中,傳入點(diǎn)的類(lèi)型可以是自定義的 Point
,也可以是 pcl::point
之類(lèi)。
例如在頭文件中的定義如下:
template<typename T> class POLYGON { public: POLYGON(); public: void convhull(std::vector<T> &input, std::vector<T> &result); };
模板函數(shù)
如模板類(lèi)中的 convhull
函數(shù)就是模板函數(shù),模板函數(shù)的輸入為各種類(lèi)型的點(diǎn),將計(jì)算后的凸包存在 result
中。 convhull
的模板參數(shù)只有T,也可以為該函數(shù)增加其它的模板參數(shù)。
例如,增加參數(shù) T1
:
template<typename T> class POLYGON { public: POLYGON(); template<typename T1> void test(T1 a); public: void convhull(std::vector<T> &input, std::vector<T> &result); };
以上為模板類(lèi)和模板函數(shù)是如何定義的,接下來(lái)將介紹它們是如何初始化的。模板函數(shù)有隱式實(shí)例化和顯示實(shí)例化,但模板類(lèi)只有顯式實(shí)例化。
1、隱式實(shí)例化
? 在模板函數(shù)的初始化在類(lèi)的內(nèi)部,即函數(shù)的實(shí)現(xiàn)在類(lèi)的內(nèi)部,例如實(shí)現(xiàn) pointFromVeh2grd
,在調(diào)用隱式實(shí)例化的模板函數(shù)時(shí),系統(tǒng)會(huì)自動(dòng)適配模板參數(shù)T。
template<typename T> class POLYGON { public: POLYGON(); T pointFromVeh2grd(const T &ptVeh, const double &vehX, const double &vehY, const float &vehYaw){ return ptGrd; } template<typename T1> void test(T1 a); public: void convhull(std::vector<T> &input, std::vector<T> &result); };
2、顯示初始化
模板函數(shù)的初始化在類(lèi)的外部,模板類(lèi)實(shí)例化 AXIS_CONVERT<int>
,這說(shuō)明 AXIS_CONVERT
類(lèi)只接受int類(lèi)型的輸入,如果輸入類(lèi)型,編譯器會(huì)報(bào)錯(cuò)。
模板函數(shù)實(shí)例化 template void AXIS_CONVERT::test<double>(double);
同樣 test
函數(shù)只接受 double
類(lèi)型的輸入。
//在源文件中進(jìn)行顯式初始化及實(shí)現(xiàn) //顯式初始化 template class AXIS_CONVERT<int>; template void AXIS_CONVERT::test<double>(double); //函數(shù)功能實(shí)現(xiàn) template<typename T> template<typename T1> void AXIS_CONVERT<T>::test(T a) { std::cout<<a<<std::endl; }
C++函數(shù)模板特化,類(lèi)模板特化
模版與特化的概念
1. 函數(shù)模版與類(lèi)模版
C++中模板分為函數(shù)模板和類(lèi)模板
- 函數(shù)模板:是一種抽象函數(shù)定義,它代表一類(lèi)同構(gòu)函數(shù)。
- 類(lèi)模板:是一種更高層次的抽象的類(lèi)定義。
2. 特化的概念
所謂特化,就是將泛型的東西搞得具體化一些,從字面上來(lái)解釋?zhuān)褪菫橐延械哪0鍏?shù)進(jìn)行一些使其特殊化的指定,使得以前不受任何約束的模板參數(shù),或受到特定的修飾(例如const或者搖身一變成為了指針之類(lèi)的東東,甚至是經(jīng)過(guò)別的模板類(lèi)包裝之后的模板類(lèi)型)或完全被指定了下來(lái)。
模板特化的分類(lèi)
針對(duì)特化的對(duì)象不同,分為兩類(lèi):函數(shù)模板的特化和類(lèi)模板的特化
1. 函數(shù)模板的特化
當(dāng)函數(shù)模板需要對(duì)某些類(lèi)型進(jìn)行特化處理,稱(chēng)為函數(shù)模板的特化。
2. 類(lèi)模板的特化
當(dāng)類(lèi)模板內(nèi)需要對(duì)某些類(lèi)型進(jìn)行特別處理時(shí),使用類(lèi)模板的特化。
3. 特化整體上分為全特化和偏特化
(1)全特化
就是模板中模板參數(shù)全被指定為確定的類(lèi)型。
全特化也就是定義了一個(gè)全新的類(lèi)型,全特化的類(lèi)中的函數(shù)可以與模板類(lèi)不一樣。
(2)偏特化
就是模板中的模板參數(shù)沒(méi)有被全部確定,需要編譯器在編譯時(shí)進(jìn)行確定。
全特化的標(biāo)志就是產(chǎn)生出完全確定的東西,而不是還需要在編譯期間去搜尋適合的特化實(shí)現(xiàn),貌似在我的這種理解下,全特化的 東西不論是類(lèi)還是函數(shù)都有這樣的特點(diǎn)
(3)兩者的差別
模板函數(shù)只能全特化,沒(méi)有偏特化(以后可能有)。
模板類(lèi)是可以全特化和偏特化的。
全特化的標(biāo)志:template <>然后是完全和模板類(lèi)型沒(méi)有一點(diǎn)關(guān)系的類(lèi)實(shí)現(xiàn)或者函數(shù)定義
偏特化的標(biāo)志:template
函數(shù)模版特化:目前的標(biāo)準(zhǔn)中,模板函數(shù)只能全特化,沒(méi)有偏特化
至于為什么函數(shù)不能偏特化,似乎不是因?yàn)檎Z(yǔ)言實(shí)現(xiàn)不了,而是因?yàn)槠鼗墓δ芸梢酝ㄟ^(guò)函數(shù)的重載完成。
示例代碼
1. 函數(shù)模板的特化
#include <iostream> #include <cstring> // 函數(shù)模板 template <class T> int compare(const T left, const T right) { std::cout <<"in template<class T>..." <<std::endl; return (left - right); } // 一個(gè)特化的函數(shù)模版 template < > int compare<const char*>(const char* left, const char* right) { std::cout <<"in special template< >..." <<std::endl; return strcmp(left, right); } // 這個(gè)其實(shí)本質(zhì)是函數(shù)重載 int compare(char* left, char* right) { std::cout <<"in overload function..." <<std::endl; return strcmp(left, right); } int main( ) { compare(1, 4); const char *left = "abcdef"; const char *right = "wild_wolf"; compare(left, right); return 0; }
2. 類(lèi)模板的特化
與函數(shù)模板類(lèi)似,當(dāng)類(lèi)模板內(nèi)需要對(duì)某些類(lèi)型進(jìn)行特別處理時(shí),使用類(lèi)模板的特化。
#include <iostream> #include <cstring> #include <cmath> #include"tt.h" // general version template<class T> class Compare { public: static bool IsEqual(const T& lh, const T& rh) { std::cout << "in the general class..." << std::endl; return lh == rh; } }; // specialize for float template<> class Compare<float> { public: static bool IsEqual(const float& lh, const float& rh) { std::cout << "in the float special class..." << std::endl; return std::abs(lh - rh) < 10e-3; } }; // specialize for double template<> class Compare<double> { public: static bool IsEqual(const double& lh, const double& rh) { std::cout << "in the double special class..." << std::endl; return std::abs(lh - rh) < 10e-6; } }; int main(void) { Compare<int> comp1; std::cout << comp1.IsEqual(3, 4) << std::endl; std::cout << comp1.IsEqual(3, 3) << std::endl; Compare<float> comp2; std::cout << comp2.IsEqual(3.14, 4.14) << std::endl; std::cout << comp2.IsEqual(3, 3) << std::endl; Compare<double> comp3; std::cout << comp3.IsEqual(3.14159, 4.14159) << std::endl; std::cout << comp3.IsEqual(3.14159, 3.14159) << std::endl; std::cout << hh<string>()("11") << std::endl; system("pause"); return 0; }
其中tt.h如下:
#include<string> using std::string; template<typename key> class hh { public: size_t operator()(const key& k) const { size_t hashVal = 0; key tmp = k; while (tmp > 0) { hashVal = 37 * hashVal + tmp % 10; tmp /= 10; } return hashVal; } }; template<> class hh<string> { public: size_t operator()(const string& key) { size_t hashVal = 0; std::cout << key << std::endl; for (char ch : key) { std::cout << "hasVal: " << hashVal << std::endl; hashVal = 37 * hashVal + ch; } return hashVal; } };
總結(jié)
以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。
相關(guān)文章
詳解C語(yǔ)言中index()函數(shù)和rindex()函數(shù)的用法
這篇文章主要介紹了C語(yǔ)言中index()函數(shù)和rndex()函數(shù)的用法,是C語(yǔ)言入門(mén)學(xué)習(xí)中的基礎(chǔ)知識(shí),要的朋友可以參考下2015-08-08c++ Protobuf解決數(shù)據(jù)傳輸瓶頸面試精講
這篇文章主要介紹了c++ Protobuf解決數(shù)據(jù)傳輸瓶頸利器面試精講,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-10-10C++ 虛函數(shù)和純虛函數(shù)的區(qū)別分析
這篇文章主要介紹了C++ 虛函數(shù)和純虛函數(shù)的區(qū)別,幫助大家更好的理解和學(xué)習(xí)c++的相關(guān)知識(shí),感興趣的朋友可以了解下2020-10-10C++11/14 線程的創(chuàng)建與分離的實(shí)現(xiàn)
這篇文章主要介紹了C++11/14 線程的創(chuàng)建與分離的實(shí)現(xiàn),文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2019-01-01C語(yǔ)言用fun函數(shù)實(shí)現(xiàn)兩個(gè)數(shù)的交換方式
這篇文章主要介紹了C語(yǔ)言用fun函數(shù)實(shí)現(xiàn)兩個(gè)數(shù)的交換方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-12-12C語(yǔ)言驅(qū)動(dòng)開(kāi)發(fā)之內(nèi)核文件的讀寫(xiě)
這篇文章主要為大家詳細(xì)介紹了C語(yǔ)言驅(qū)動(dòng)開(kāi)發(fā)中內(nèi)核文件的讀寫(xiě)的系列函數(shù),文中的示例代碼講解詳細(xì),感興趣的小伙伴可以跟隨小編一起學(xué)習(xí)一下2023-06-06C語(yǔ)言實(shí)現(xiàn)文本文件/二進(jìn)制文件格式互換
這篇文章主要為大家詳細(xì)介紹了C語(yǔ)言實(shí)現(xiàn)文本文件和二進(jìn)制文件格式互換,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2019-03-03詳解如何配置CLion作為Qt5開(kāi)發(fā)環(huán)境的方法
這篇文章主要介紹了詳解如何配置CLion作為Qt5開(kāi)發(fā)環(huán)境的方法,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2021-04-04