摘要:文章目錄模板模板的概念函數模板函數模板語法函數模板注意事項函數模板案例普通函數與函數模板的區別普通函數與函數模板的調用規則模板的局限性類模板類模板語法類模板與函數模板區別類模板中成員函數創建時機類模板對象做函數參數類模
本階段主要針對C++泛型編程和STL技術做詳細講解,探討C++更深層的使用
模板就是建立通用的模具,大大提高復用性
模板的特點:
函數模板作用:建立一個通用函數,其函數返回值類型和形參類型可以不具體制定,用一個虛擬的類型來代表。
語法:
template<typename T>函數聲明或定義
解釋:
#include using namespace std;//函數模板//兩個整型交換函數void swapInt(int &a, int &b) { int temp = a; a = b; b = temp;}//交換兩個浮點型函數void swapDouble(double& a, double& b) { double temp = a; a = b; b = temp;}//函數模板template<typename T> //聲明一個模板,告訴編譯器后面代碼中緊跟著的T不要報錯,T是一個通用數據類型void mySwap(T& a, T& b) { T temp = a; a = b; b = temp;}void test01() { float a = 10; float b = 20; //兩種方式使用函數模板 //1、自動類型推導 mySwap(a, b); cout << "a:" << a << endl; cout << "b:" << b << endl; cout << "/n"; //2、顯示指定類型 mySwap<float>(a, b); cout << "a:" << a << endl; cout << "b:" << b << endl;}int main() { test01(); system("pause"); system("cls");}
總結:
注意事項:
//利用模板提供通用的交換函數template<class T>void mySwap(T& a, T& b){ T temp = a; a = b; b = temp;}// 1、自動類型推導,必須推導出一致的數據類型T,才可以使用void test01(){ int a = 10; int b = 20; char c = "c"; mySwap(a, b); // 正確,可以推導出一致的T //mySwap(a, c); // 錯誤,推導不出一致的T類型}// 2、模板必須要確定出T的數據類型,才可以使用template<class T>void func(){ cout << "func 調用" << endl;}void test02(){ //func(); //錯誤,模板不能獨立使用,必須確定出T的類型 func<int>(); //利用顯示指定類型的方式,給T一個類型,才可以使用該模板}int main() { test01(); test02(); system("pause"); return 0;}
總結:使用模板時必須確定出通用數據類型T,并且能夠推導出一致的類型
案例描述:
利用函數模板封裝一個排序的函數,可以對不同數據類型數組進行排序
排序規則從大到小,排序算法為選擇排序
分別利用char數組和int數組進行測試
#include using namespace std;//實現通用 對數組進行排序的函數//從大到小 選擇排序//測試 char數組、 int數組//交換函數模板template<class T>void mySwap(T& a, T& b) { T temp = a; a = b; b = temp;}//排序算法:選擇排序,每次選擇最大的一個放在前面template<class T>void mySort(T arr[], int len) { for (int i = 0; i < len; i++) { int max = i; //認定最大值的下標 for (int j = i + 1; j < len; j++) { if (arr[max] < arr[j]) { max = j; } } if (max != i) { //交換max和i元素 mySwap(arr[max], arr[i]); } }}//提供打印數組模板template<class T>void printArray(T arr[], int len) { for (int i = 0; i < len; i++) { cout << arr[i] << " "; } cout << endl;}void test01() { //測試char數組 char charArr[] = "badcfe"; int num = sizeof(charArr) / sizeof(char); mySort(charArr, num); printArray(charArr, num);}void test02() { //測試int數組 int intArr[] = { 7,5,1,3,9,2,4,6,8 }; int num = sizeof(intArr) / sizeof(int); mySort(intArr, num); printArray(intArr, num);}int main() { test01(); test02(); system("pause"); system("cls");}
f e d c b a9 8 7 6 5 4 3 2 1請按任意鍵繼續. . .
普通函數與函數模板區別:
#include using namespace std;//普通函數和函數模板的區別//1、普通函數調用可以發生隱式類型轉換//2、函數模板 用自動類型推導,不可以發生隱式類型轉換//3、函數模板 用顯示指定類型,可以發生隱式類型轉換//普通函數int myAdd01(int a, int b) { return a + b;}//函數模板template<class T>T myAdd02(T a, T b) { return a + b;}void test01() { int a = 10; int b = 20; char c = "c"; //99 //cout << myAdd01(a, b) << endl; cout << myAdd01(a, c) << endl; //1、自動類型推導 不會發生隱式類型轉換 //cout << myAdd02(a, c) << endl; //報錯,無法推導出一致的T //2、顯示指定類型 會發生隱式類型轉換 cout << myAdd02<int>(a, c) << endl; cout << myAdd02<char>(a, c) << endl;}int main() { test01(); system("pause"); system("cls");}
總結:建議使用顯示指定類型的方式,調用函數模板,因為可以自己確定通用類型T
調用規則如下:
#include using namespace std;//普通函數與函數模板的調用規則//1、如果函數模板和普通函數都可以調用,優先調用普通函數//2、可以通過空模板參數列表 強制調用 函數模板//3、函數模板可以發生函數重載//4、如果函數模板可以產生更好的匹配,優先調用函數模板void myPrint(int a, int b){ cout << "調用的普通函數" << endl;}template<class T>void myPrint(T a, T b) { cout << "調用的模板" << endl;}template<class T>void myPrint(T a, T b, T c) { cout << "調用重載的模板" << endl;}void test01() { int a = 10; int b = 20; myPrint(a, b); //調用的普通函數 //通過空模板參數列表,強制調用函數模板 myPrint<>(a, b); //調用模板 myPrint<>(a, b, 100); //調用重載的模板 //如果函數模板可以產生更好的匹配,優先調用函數模板 char c1 = "a"; char c2 = "b"; myPrint(c1, c2); //調用模板}int main() { test01(); system("pause"); system("cls");}
調用的普通函數調用的模板調用重載的模板調用的模板請按任意鍵繼續. . .
總結:既然提供了函數模板,最好就不要提供普通函數,否則容易出現二義性
局限性:模板的通用性并不是萬能的
template<class T> void f(T a, T b) { a = b; }
在上述代碼中提供的賦值操作,如果傳入的a和b是一個數組,就無法實現了
template<class T> void f(T a, T b) { if(a > b) { ... } }
在上述代碼中,如果T的數據類型傳入的是像Person這樣的自定義數據類型,也無法正常運行
因此C++為了解決這種問題,提供模板的重載,可以為這些特定的類型提供具體化的模板
#include using namespace std;//模板局限性//特定數據類型 需要用具體方式做特殊實現class Person {public: Person(string name, int age) { this->m_Name = name; this->m_Age = age; } //姓名 string m_Name; //年齡 string m_Age;};//對比兩個數據是否相等函數template<class T>bool myCompare(T& a, T& b) { if (a == b) { return true; } else { return false; }}//利用具體化Person的版本實現代碼,具體化優先調用template<> bool myCompare(Person& p1, Person& p2) { if (p1.m_Name == p2.m_Name && p1.m_Age == p2.m_Age) { return true; } else { return false; }}void test01() { int a = 10; int b = 20; bool ret = myCompare(a, b); if (ret) { cout << "a == b" << endl; } else { cout << "a != b" << endl; }}void test02() { Person p1("Tom", 10); Person p2("Tom", 10); bool ret = myCompare(p1, p2); if (ret) { cout << "p1 == p2" << endl; } else { cout << "p1 != p2" << endl; }}int main() { test01(); test02(); system("pause"); system("cls");}
總結:
類模板作用:建立一個通用類,類中的成員 數據類型可以不具體制定,用一個虛擬的類型來代表。
語法:
template<typename T>類
解釋:
#include using namespace std;//類模板template<class NameType, class AgeType>class Person {public: Person(NameType name, AgeType age) { this->m_Name = name; this->m_Age = age; } void showPerson() { cout << "name:" << this->m_Name << endl; cout << "age:" << this->m_Age << endl; } NameType m_Name; AgeType m_Age;};void test01() { Person<string, int> p1("張三", 18); cout << p1.m_Name << "," << p1.m_Age << endl; p1.showPerson();}int main() { test01(); system("pause"); system("cls");}
張三,18name:張三age:18請按任意鍵繼續. . .
總結:類模板和函數模板語法相似,在聲明模板template后面加類,此類稱為類模板
類模板與函數模板區別主要有兩點:
#include using namespace std;//類模板和函數模板區別template<class NameType, class AgeType = int>class Person {public: Person(NameType name, AgeType age) { this->m_Name = name; this->m_Age = age; } void showPerson() { cout << "name:" << this->m_Name << endl; cout << "age:" << this->m_Age << endl; } NameType m_Name; AgeType m_Age;};void test01() { //Person p("張三", 18); //1、類模板沒有自動類型推導使用方式 Person<string, int> p("張三", 18); p.showPerson();}//2、類模板在模板參數列表中可以有默認參數void test02() { Person<string> p2("李四", 20); //后一個參數默認整型, 默認參數只有類模板有,函數模板沒有 p2.showPerson();}int main() { test01(); test02(); system("pause"); system("cls");}
name:張三age:18name:李四age:20請按任意鍵繼續. . .
總結:
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/122421.html
摘要:只讀目的是防止程序意外地修改了它的指令。全局區存放全局變量靜態變量和常量除了修飾的局部變量。程序結束時由操作系統釋放。由編譯器自動分配和釋放。注意不要返回局部變量的地址。 ...
摘要:與都繼承自類,在中也是使用字符數組保存字符串,,這兩種對象都是可變的。采用字節碼的好處語言通過字節碼的方式,在一定程度上解決了傳統解釋型語言執行效率低的問題,同時又保留了解釋型語言可移植的特點。 String和StringBuffer、StringBuilder的區別是什么?String為什么是不可變的? String和StringBuffer、StringBuilder的區別 可變性...
摘要:目前,中關村黑馬程序員訓練營已成長為行業學員質量好課程內容深企業滿意的移動開發高端訓練基地,并被評為中關村軟件園重點扶持人才企業。黑馬程序員的學員篩選制度,遠比現在以上的企業招聘流程更為嚴格。系統的學習可以參考w3c的教程 web概念概述 * JavaWeb: * 使用Java語言開發基于互聯網的項目 * 軟件架構: 1. C/S: Client/Server 客戶端/服務...
摘要:而面向搜索引擎,就是我們要及時的使用百度谷歌遇到問題無法解決,先別急著放棄,可以去網絡尋找答案,你的坑大部分別人都已經走過了,大部分都可以找到合適的解決方案。 showImg(https://segmentfault.com/img/remote/1460000019236352?w=866&h=456); 前言: ●眾多的語言,到底哪一門才是適合我的?●我們為什么要學習Java語言呢...
閱讀 2440·2021-11-23 09:51
閱讀 1867·2021-10-13 09:40
閱讀 1372·2021-09-30 10:01
閱讀 589·2021-09-26 09:46
閱讀 2232·2021-09-23 11:55
閱讀 1385·2021-09-10 10:51
閱讀 2240·2021-09-09 09:33
閱讀 2227·2019-08-29 17:25