您好,登錄后才能下訂單哦!
本文小編為大家詳細(xì)介紹“C++數(shù)據(jù)結(jié)構(gòu)模板進(jìn)階實(shí)例分析”,內(nèi)容詳細(xì),步驟清晰,細(xì)節(jié)處理妥當(dāng),希望這篇“C++數(shù)據(jù)結(jié)構(gòu)模板進(jìn)階實(shí)例分析”文章能幫助大家解決疑惑,下面跟著小編的思路慢慢深入,一起來學(xué)習(xí)新知識(shí)吧。
模板參數(shù)分類類型形參與非類型形參。
類型模板形參:出現(xiàn)在模板參數(shù)列表中,跟在class或者typename后面的參數(shù)類型名稱。
非類型模板形參:用一個(gè)常量作為模板的一個(gè)參數(shù),必須是整形家族中的類型參數(shù),否則不行。他在模板中可以當(dāng)常量使用。
實(shí)例:
// 類型模板參數(shù) namespace wxj { // 非類型模板參數(shù) N 是一個(gè)常量參數(shù),只能是整形家族的:int short char long long long 自定義類型和其他類型都不能作費(fèi)類型模板參數(shù) // 必須在編譯期就能確認(rèn)結(jié)果 template<class T, size_t N = 10> class Array { public: Array() :_size(N) {} T& operator[](size_t i) { return _arr[i]; } const T& operator[](size_t i) const { return _arr[i]; } size_t size() { return _size; } bool empty() { return _size == 0; } private: T _arr[N]; size_t _size; }; void TestArray() { Array<int, 5> arr; for (size_t i = 0; i < arr.size(); ++i) { arr[i] = i; } for (size_t i = 0; i < arr.size(); ++i) { cout << arr[i] << " "; } cout << endl; } } int main() { wxj::TestArray(); return 0; }
代碼運(yùn)行結(jié)果如下:
看上面,我們定義了一個(gè)數(shù)組類,空間大小由N決定,類型是Array<T, size_t>
注意:
非類型形參必須是整形家族中的類型,浮點(diǎn)數(shù)和類對(duì)象都不行。
非類型的模板形參必須在編譯期間就能確認(rèn)結(jié)果。
模板特化:在原模板類的基礎(chǔ)上,針對(duì)特殊類型所進(jìn)行的特殊化的實(shí)現(xiàn)。分為函數(shù)模板特化 和類模板特化。
特化的步驟
必須先有一個(gè)基礎(chǔ)的函數(shù)模板
關(guān)鍵字template后面接一對(duì)空的尖括號(hào)<>
函數(shù)名后跟一對(duì)尖括號(hào)<>,里面指定需要的特化的類型
函數(shù)形參列表:必須和函數(shù)模板的基礎(chǔ)參數(shù)類型完全一致
實(shí)例
// 模板的特化 模板的特殊化 template<class T> bool IsEqual(T& left, T& right) { return left == right; } // 特化 針對(duì)某些類型進(jìn)行特殊化處理 template<> bool IsEqual<const char* const>(const char* const& left, const char* const& right) { return strcmp(left, right) == 0; }
注意: 一般情況下如果函數(shù)模板遇到不能處理或者處理有誤的類型,為了實(shí)現(xiàn)簡單通常都是將該函數(shù)直接給出。
bool IsEqual(char* left, char* right) { return strcmp(left, right) == 0; }
類模板的特化分為全特化和偏特化。
全特化: 對(duì)類模板參數(shù)列表的類型全部都確定(明確指定)
template <class T1, class T2> class Date { public: Date() { cout << "Date<T1, T2>" << endl; } private: T1 _d1; T2 _d2; }; // 全特化 template<> class Date<int, double> { public: Date() { cout << "Date<int, double>" << endl; } private: int _d1; double _d2; };
偏特化: 堆類模板的參數(shù)列表中部分參數(shù)進(jìn)行確定化分為部分特化和參數(shù)進(jìn)一步限制
部分特化
// 部分 template<class T2> class Date<int, T2> { public: Date() { cout << "Date<int, T2>" << endl; } private: int _d1; T2 _d2; };
參數(shù)進(jìn)一步限制 如下有T*和T&,是模板的類型轉(zhuǎn)為指針類型和引用類型
// 參數(shù)進(jìn)一步限制 堆模板參數(shù)更進(jìn)一步的條件限制 template <class T1, class T2> class Date<T1*, T2&> { public: Date(int& a) :_d2(a) { cout << "Date<T1*, T2&>" << endl; } private: T1* _d1; T2& _d2; };
實(shí)例 我們試著實(shí)例化幾個(gè)對(duì)象,看他們用的是哪個(gè)模板
int main() { Date<int, int> d1; Date<int, double> d2; Date<int, float> d3; int a = 10; Date<int*, int&> d4(a); return 0; }
代碼運(yùn)行結(jié)果:
分離編譯: 我們對(duì)這個(gè)應(yīng)該是不陌生的,就是把函數(shù)的聲明放在一個(gè)叫**.h的文件中,實(shí)現(xiàn)都放在一個(gè)叫.cpp**的文件中,這樣方便我們管理。
下面我們試著對(duì)模板進(jìn)行分離編譯:
// a.h #pragma once // 普通函數(shù) void Swap(int& a, int& b); // 函數(shù)模板 template<class T> T Add(const T& a, const T& b); // a.cpp #define _CRT_SECURE_NO_WARNINGS 1 #include "a.h" // 普通函數(shù) void Swap(int& a, int& b) { int tmp = a; a = b; b = tmp; } // 函數(shù)模板 template<class T> T Add(const T& a, const T& b) { return a + b; } // test.cpp #include "a.h" int main() { int a = 3; int b = 4; Swap(a, b); cout << "a = " << a << " b = " << b << endl; cout << Add(a, b) << endl; return 0; }
代碼運(yùn)行結(jié)果如下
代碼運(yùn)行時(shí)發(fā)生了報(bào)錯(cuò),說Add這個(gè)函數(shù)是沒有見過的。得出結(jié)論:函數(shù)模板不能分離編譯,普通函數(shù)可以。
為什么會(huì)這樣呢?
C++程序運(yùn)行一般經(jīng)過幾個(gè)階段:預(yù)處理——>編譯——>匯編——>鏈接(更詳細(xì)的內(nèi)容可以參考往期博客——程序的編譯)
模板在.cpp中定義了,由于不知道T的類型,所以沒有對(duì)模板進(jìn)行實(shí)例化。
a.h 和 a.cpp 走的是兩條不同的路,兩條路都沒有對(duì)模板進(jìn)行實(shí)例化(因?yàn)椴恢繲的類型)。
因?yàn)闆]有對(duì)模板進(jìn)行實(shí)例化,所以沒有函數(shù)參數(shù),也就沒有函數(shù)地址,所以在鏈接時(shí),test.cpp中的調(diào)用Add函數(shù)時(shí),沒有函數(shù)地址,call調(diào)用不到Add函數(shù),所以報(bào)錯(cuò)。
解決方法:
暴力:不分離編譯,統(tǒng)一放在一個(gè).h或.hpp的文件中
模板定義位置顯示實(shí)例化(不推薦,這樣就失去了泛型的特點(diǎn))
讀到這里,這篇“C++數(shù)據(jù)結(jié)構(gòu)模板進(jìn)階實(shí)例分析”文章已經(jīng)介紹完畢,想要掌握這篇文章的知識(shí)點(diǎn)還需要大家自己動(dòng)手實(shí)踐使用過才能領(lǐng)會(huì),如果想了解更多相關(guān)內(nèi)容的文章,歡迎關(guān)注億速云行業(yè)資訊頻道。
免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場,如果涉及侵權(quán)請(qǐng)聯(lián)系站長郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。