文章目錄
- 泛型編程:
- 概念
- 函數模板
- 概念:
- 🚩函數模板格式
- 原理:
- 🚩函數模板實例化
- 與非模板函數共存
- 類模板
- 類模板實例化
泛型編程:
概念
🚩編寫與類型無關的通用代碼,是代碼復寫一種手段,模板是泛型編程的基礎,
如果我們想寫一個通用的交換代碼 ?
void Swap(int& a, int& b)
{int t = a;a = b;b = t;
}
void Swap(double& a, double& b)
{int t = a;a = b;b = t;
}
void Swap(char& a, char& b)
{int t = a;a = b;b = t;
}
我們需要寫各種類型代碼,由于函數重載這樣可以實現,但這也太麻煩了!!
如果有個模具,我們需要什么類型 加進去就能用多好,
函數模板
概念:
函數模板代表了一個函數家族,該函數模板與類型無關,在需要時實參化,根據實參類型產生相應特殊函數,
🚩函數模板格式
template<typename T1, typename T2,…,typename Tn>
返回值類型 函數名(參數列表){}
所以交換函數實現:
template<typename T>
void Swap(T &a,T& b)
{T temp = a;a = b;b = t;
}
注意:typename是定義模板參數的關鍵字,也可以用class代替(但不能用struct)
原理:
在編譯階段,編譯器會通過根據傳入的實參類型推演出正確的模板參數類型,然后編譯器生成一份正確的代碼
🚩函數模板實例化
隱式實例化:讓編譯器自動識別:
#include <iostream>
using namespace std;
template<typename T>
void Swap(T &a,T& b)
{T temp=a;a = b;b = temp;cout << a << " " << b<<endl;
}
int main()
{int a1 = 10, a2 = 20;double b1 = 10.5, b2 = 20.5;Swap(a1, a2);Swap(b1, b2);return 0;
}
20 10
20.5 10.5
但是有個問題,如下
int a3 = 30;
double b3 = 30.5;
Swap(a3, b3);
報錯了,
因為就一個T,不知道是int還是double了,
1,我們可以強轉
2,顯性實例化
int a3 = 30;
double b3 = 30.5;
Swap((double)a3, b3);
出錯了,但沒辦法QAQ
強轉會產生臨時變量,引用不能接受,實例化也沒用,模板參數加const又不能交換QAQ,所以我們只能先換個函數繼續講QAQ
顯性實例化:在函數名后接<>,里面指定模板函數實際類型
#include <iostream>
using namespace std;
template<typename T>
void Add(const T& a,const T& b)
{cout << a + b << endl;
}
int main()
{int a4 = 40;double b4 = 40.5;Add((double)a4, b4);Add<int>(a4, b4);return 0;
}
80.5
80
與非模板函數共存
模板函數是可以和非模板函數共名的,編譯器會優先考慮非模板函數,
#include <iostream>
using namespace std;
template<typename T>
void Add(const T& a,const T& b)
{cout << a + b << endl;
}
void Add(int a, int b)
{cout << "sum=";cout << a + b << endl;
}int main()
{int a4 = 40;double b4 = 40.5;Add((double)a4, b4);Add<int>(a4, b4);Add(1, 2);Add(1,2.1);return 0;
}
80.5
80
sum=3
sum=3
后兩個用非模板,說明如果合適,編譯器優先非模板函數,處理不了就用模板函數,
注意:模板函數不能自動轉換,非模板函數能自動轉換類型
類模板
格式:
template<class T1,class T2,…,class T3>
class 類模板名 {
};
//實現一個動態順序表
template<class T>
class vector
{
public:vector(int capacity=0):_pDate(new T[capacity]),_size(0),_capacity(capacity){}T& operator [](size_t pos){if(pos<size)return _pDate[pos];}size_t size(){return _size;}~vector();//類中聲明,類外定義
private:T* _pDate;size_t _size;size_t _capacity;
};
template<class T>
vector<T>::~vector()
{if (_pDate)delete[] _pDate;_size = _capacity = 0;
}
如果在類外定義函數,需要加模板列表
類模板實例化
類模板實例化和函數模板實例化不同,需要在類模板名字后面加<>,里面存的是需要實例化的類型
int main()
{vector<int> s1;vector<double> s2;return 0;
}
類模板名字不是真正的類,實例化的結果才是真正的類,