模版-基礎
阿新 • • 發佈:2021-06-19
類--模具
例項化出來的物件--模具做出來的產品
模版--模具的圖紙
模版--例項化--》類(模具)---例項化物件(產品)
一.函式模版
模板和特例化返回值一致,函式名一致,引數格式一致
模板型別是在編譯期進行確定,確定好模板型別之後例項化成具體的
函式/類,以供使用
模板是否都會例項化呢?
特例化會直接編譯,不用例項化
普通模板只有呼叫才會編譯
模板只有呼叫了才會例項化,會根據呼叫的型別例項化出對應的函
數/類
模板在編譯期間進行例項化
普通函式>特例化版本>模版
普通函式:整形,浮點型
template<typename T> bool compare(T a, T b)//比較 含參{ cout << "bool compare(T a, T b) " << typeid(T).name() << endl;//進行輸出 // typeid(T).name() 輸出型別名 return a > b;//若為真 返回值 為假返回0 }
函式模板不能滿足個別的型別需求的情況下
函式模板的特例化
函式過載 是在編譯期確定需要呼叫的函式
函式模板 是在編譯期確定需要例項化的函式型別
函式模板例項化出來的多個函式之間是過載關係--包括函式模板的特例化
靜多型包含:編譯期間的多型 ,函式過載 ,模板
函式過載:
bool compare(int a, int b) { cout << "bool compare(int a, int b)" << endl; return a > b; } bool compare(char a, char b) { return a > b; } bool compare(const char* a,const char* b)//傳常量字串 { cout << "bool compare(const char* a,const char* b)" << endl;return strcmp(a,b) > 0; }
特例化版本:
字串:
template<> bool compare<const char*>(const char* a, const char* b) { cout << "bool compare<const char*>(const char* a, const char* b)" << endl; return strcmp(a, b) > 0; }
氣泡排序的模板特例化
寫const char*
普通:
template<typename ZPL>//先指定型別代表 void Msort(ZPL* arr, int len) { if (NULL == arr) { return; } ZPL tmp = ZPL();// 相當於int tmp=0; for (int i = 0; i < len; i++) { for (int j = 0; j < len - i - 1; j++) { if (arr[j] < arr[j + 1]) { tmp = arr[j]; arr[j] = arr[j + 1]; arr[j + 1] = tmp; } } } }
特例化:
template<> void Msort<const char*>(const char** arr, int len)//const char* 又因為是陣列 *arr { if (NULL == arr) { return; } const char* tmp = NULL;//進行指定 for (int i = 0; i < len; i++) { for (int j = 0; j < len - i - 1; j++) { if (arr[j] && arr[j + 1])//判斷他兩同時不為空 { if (strcmp(arr[j], arr[j + 1]) < 0)//const char* 時使用strcmp { tmp = arr[j]; arr[j] = arr[j + 1]; arr[j + 1] = tmp; } } } } }
函式模版:
template<typename T> class Arr { private: T* _arr; int _len; int _size; void revert() { _len = _len << 1; T* tmp = new T[_len]; memset(tmp, T(), _len); for (int i = 0; i < _size; i++) { tmp[i] = _arr[i]; } delete[]_arr; _arr = tmp; } public: Arr(int len = 10); Arr(T* arr, int size); Arr(const Arr& src); ~Arr(); Arr& operator=(const Arr& src); void push_back(T val); void sort(); bool is_full() { return _size == _len; } int size()//排序時使用,可不使用友元 { return _size; } T* get_arr() { return _arr; } //template<typename T>//字母T 可換其他字母 //friend ostream& operator<<(ostream& out, Arr<T>& src);//T可換 }; template<typename T>//重新定義T Arr<T>::Arr(int len)//宣告作用域Arr<T> 上面是預設值,下面是引數 { _len = len; _arr = new T[_len]; memset(_arr, T(), _len);//進行初始化 T型別 預設值為len _size = 0; } template<typename T> Arr<T>::Arr(T* arr, int size) { _len = size; _size = size; _arr = new T[_len]; memset(_arr, T(), _len); for (int i = 0; i < _len; i++) { _arr[i] = arr[i]; } } template<typename T> Arr<T>::Arr(const Arr& src)//拷貝構造 { _len = src._len; _size = src._size; _arr = new T[_len]; memset(_arr, T(), _len); for (int i = 0; i < _size; i++)//防止淺拷貝 { _arr[i] = src._arr[i]; } } template<typename T> Arr<T>::~Arr() { delete[]_arr; _arr = NULL; _size = _len = 0; } template<typename T> Arr<T>& Arr<T>::operator=(const Arr& src)//等號運算子 { if (&src == this) { return *this; } delete _arr; _len = src._len; _size = src._size; _arr = new T[_len]; memset(_arr, T(), _len); for (int i = 0; i < _size; i++) { _arr[i] = src._arr[i]; } return *this; } template<typename T> void Arr<T>::push_back(T val)//從後面放 { if (is_full()) { revert();//申請空間 } _arr[_size++] = val; } template<typename T> void Arr<T>::sort()//排序 { T tmp = T(); for (int i = 0; i < _size; i++) { for (int j = 0; j < _size - i - 1; j++) { if (_arr[j] < _arr[j + 1]) { tmp = _arr[j]; _arr[j] = _arr[j + 1]; _arr[j + 1] = tmp; } } } } template<typename T>//重新定義T (Arr<T>中的T) ostream& operator<<(ostream& out, Arr<T>& src)//類外輸出運算子過載 { for (int i = 0; i < src.size(); i++) { cout << src.get_arr()[i] << " "; } cout << endl; return out; }