目錄
一. 函數模版
1. 格式 原理
2. 函數模版的實例化
二. 類模板
void Swap(int& left, int& right)
{int temp = left;left = right;right = temp;
}void Swap(double& left, double& right)
{double temp = left;left = right;right = temp;
}void Swap(char& left, char& right)
{char temp = left;left = right;right = temp;
}
使用函數重載太麻煩
模具,填充不同類型,生成具體類型的代碼
泛型編程:編寫與類型無關的通用代碼,是代碼復用的一種手段。模板是泛型編程的基礎
一. 函數模版
1. 格式 原理
template<typename T1, typename T2, ......, typename Tn>
返回類型 函數名(參數列表)
{ }
typename是用來定義模板參數關鍵字,也可以使用class,不能使用struct
模板參數作用范圍:緊跟的 { }
template<typename T> // 模板參數 -- 類型
void Swap(T& left, T& right)
{T temp = left;left = right;right = temp;
}template<typename T1, typename T2>
T1 Func (const T1& x, const T2& y)
{cout << x << " " << y << endl;return x;
}
int main()
{int a = 0, b = 1;double c = 1.1, d = 2.2;Swap(a, b);Swap(c, d);// Date d1(1949, 10, 1), d2(2015, 7, 3);Func(1, 2);Func(1, 2.2);return 0;
}
調用的是模版實例化出的函數(模板就是將本來應該我們做的重復的事情交給了編譯器 )
C++庫里面有。不需要寫Swap,也不用寫模版。直接使用
int main()
{int a = 0, b = 1;double c = 1.1, d = 2.2;swap(a, b);swap(c, d);// Date d1(1949, 10, 1), d2(2015, 7, 3);return 0;
}
2. 函數模版的實例化
隱式實例化:讓編譯器根據實參 推演模板參數的實際類型
顯示實例化:在函數名后的<>中 指定模板參數的實際類型
template<typename T>
T Add(const T& left, const T& right)
{return left + right;
}template<typename T>
T* Alloc(int n)
{return new T[n];
}int main()
{ int a1 = 10, a2 = 20;double d1 = 10.1, d2 = 20.2;cout << Add(a1, a2) << endl;cout << Add(d1, d2) << endl;// cout << Add(a1, d1) << endl; 報錯:編譯器無法確定T的類型// 解決方案1:用戶自己強制轉換cout << Add(a1, (int)d1) << endl;cout << Add((double)a1, d1) << endl;// 解決方案2:顯示實例化cout << Add<int>(a1, d1) << endl;cout << Add<double>(a1, d1) << endl;// 有些函數無法自動推,只能顯示實例化double* p1 = Alloc<double>(10);return 0;
}
類型轉換會產生臨時變量(常性)。Add(a1, (int)d1) 這里不是把 d1 傳給 right,所以 Add 要加 const
二. 類模板
template<class T1, class T2, ..., class Tn>
class 類模板名
{
????????// 類內成員定義
};
普通類,類名和類型是一樣
類模板,類名和類型不一樣
類名:Stack
類型:Stack<T>
構造函數不一定用T這個參數,所以類模板都無法通過推演實例化,類都是顯示實例化
template<class T>
class Stack
{
public:Stack(int capacity = 4){_a = new T[capacity];_capacity = capacity;_size = 0;}void Push(const T& Date){// CheckCapacity();_a[_size] = Date;_size++;}~Stack(){if (_a){free(_a);_a = nullptr;_capacity = 0;_size = 0;}}private:T* _a;int _capacity;int _size;
};int main()
{Stack<int> s1; // intStack<double> s2; // doubleStack<char> s3; // char// Stack<int, double>s4; 多個模板參數return 0;
}
類模板的聲明和定義分離是別致的
類模板的聲明和定義最好不要分離到 2個文件,會報錯(后面講)
template<class T>
class Stack
{
public:Stack(int capacity = 4);void Push(const T& Date);~Stack(){if (_a){free(_a);_a = nullptr;_capacity = 0;_size = 0;}}private:T* _a;int _capacity;int _size;
};template<class T>
Stack<T>::Stack(int capacity)
{_a = new T[capacity];_capacity = capacity;_size = 0;
}template<class T>
void Stack<T>::Push(const T& data)
{// CheckCapacity();_a[_size] = data;_size++;
}
本篇的分享就到這里了,感謝觀看,如果對你有幫助,別忘了點贊+收藏+關注。
小編會以自己學習過程中遇到的問題為素材,持續為您推送文章