## [$]一.實例化
### 1.隱式實例化
模板被使用時,進行的模板的實例化。
對于類模板,若成員函數不使用,則不會進行實例化。
+ **發生時機** 模板被使用時。
+ **缺點** 相同的模板實例可能出現在多個對象文件中,造成了一定的額外開銷。
#### 例1
```c++
template <typename T>
T add(const T &t1,const T &t2)
{
return t1+t2;
}
```
調用:
```c++
f(200,700);//隱式實例化
f<int>(300,600);//隱式實例化:盡管指定了模板實參,但模板仍在被使用時才進行實例化。
```
### [11+]2.顯式實例化
1. 聲明顯式實例化:告訴編譯器在其他地方有顯式實例化的定義。
+ 必須出現在使用之前,防止使用時的初始化。
```c++
extern template class Array<int>;//類模板顯式聲明
extern template int add(const int &,const int &);//函數模板顯式聲明
```
2. 定義顯式實例化:只能定義一次,此時編譯器會為該模板生成代碼。
+ 當顯式實例化類模板時,會實例化所有的成員函數。
```c++
template class Array<int>;//類模板顯式定義
template int add(const int &,const int &);//函數模板顯式定義
```
## [$]二.模板特例化
### 1.基本概念
1. **概念** 模板特例化是函數模板、類模板、成員模板的 **重定義** ,其中指定了部分或全部模板參數。
2. 模板特例化版本必須出現在原模板的聲明之后。
3. 模板特例化的本質是實例化一個模板,而非重載它。
4. 當編譯器匹配到特例化的版本時,編譯器會直接使用特例化的版本,而不是重新實例化原來的模板。
### 2.函數模板特例化
當我們特例化一個函數模板時,必須為原模板中的每個模板參數都提供模板實參。且提供的模板實參必須與模板匹配。
#### 例2
下面是一個函數的多個定義,以支持字符串、字符數組的比較。
```c++
//通用模板
template <typename T>
int compare(const T &t1, const T &t2)
{
cout << "調用第一個版本" << endl;
if (t1 > t2)
return 1;
if (t1 == t2)
return 0;
if (t1 < t2)
return -1;
return 0;
}
//這是重載,不是特例化,用于字符數組的傳入
template <unsigned N1, unsigned N2>
int compare(const char (&p1)[N1], const char (&p2)[N2])
{
cout << "調用第二個版本" << endl;
return strcmp(p1, p2);
}
//特例化的模板,T=const char *,用于字符指針的傳入
template <>
int compare(const char *const &p1, const char *const &p2)
{
cout << "調用第三個版本" << endl;
return strcmp(p1, p2);
}
```
調用:
```c++
const char *p1 = "apple";
const char *p2 = "zoo";
cout << compare(10, 9) << endl;
cout << compare("apple", "zoo") << endl;
cout << compare(p1, p2) << endl;
```
>[test]
>調用第一個版本
>1
>調用第二個版本
>-1
>調用第三個版本
>-1
### 3.類模板特例化
+ 與函數模板不同,類模板的特例化不必為所有模板參數提供實參。
+ 一個類模板的部分特例化本身是一個模板,使用它時還須提供其余的模板實參。
```c++
//模板
template <typename T>
class A {
//code
};
//特例化
class A<char *> {
//code
};
//部分特例化
template <typename T>
class A<T&> {
//code
};
```
### 4.特例化成員
+ 與函數模板類似,需要提供全部模板實參。
```c++
template <typename T>
class Array {
private:
static int size;
//其他數據成員...
public:
void output()
{
//code
}
//其他函數...
};
//特例化成員函數
template <>
Array<int>::output()
{
//code
}
//特例化靜態數據成員
template <>
Array<int>::size = 20;
```
- 閱讀說明
- 1.1 概述
- C++基礎
- 1.2 變量與常量
- 1.2.1 變量
- 1.2.2 字面值常量
- 字符型常量
- 數值型常量
- 1.2.3 cv限定符
- 1.3 作用域
- 1.3.1 標識符
- 1.3.2 *命名空間
- 1.3.3 作用域
- 1.3.4 可見性
- 1.4 數據類型
- 1.4.1 概述
- 1.4.2 處理類型
- 類型別名
- * auto說明符
- * decltype說明符
- 1.4.3 數組
- 1.4.4 指針
- 1.4.5 引用
- 1.5 表達式
- 1.5.1 概述
- 1.5.2 值的類別
- 1.5.3 *初始化
- 1.5.4 運算符
- 算術運算符
- 邏輯和關系運算符
- 賦值運算符
- 遞增遞減運算符
- 成員訪問運算符
- 位運算符
- 其他運算符
- 1.5.5 *常量表達式
- 1.5.6 類型轉換
- 第2章 面向過程編程
- 2.1 流程語句
- 2.1.1 條件語句
- 2.1.2 循環語句
- 2.1.3 跳轉語句
- 2.1.4 *異常處理
- 2.2 函數
- 2.2.1 概述
- 2.2.2 函數參數
- 2.2.3 內置函數
- 2.2.4 函數重載
- 2.2.5 * 匿名函數
- 2.3 存儲和生命期
- 2.3.1 生命周期與存儲區域
- 2.3.2 動態內存
- 2.4 *預處理命令
- 第3章 面向對象編程
- 3.1 概述
- 3.2 類和對象
- 3.3 成員
- 3.3.1 訪問限制
- 3.3.2 常成員
- 3.3.3 靜態成員
- 3.3.4 成員指針
- 3.3.5 this指針
- 3.4 特殊的成員函數
- 3.4.1 概述
- 3.4.2 構造函數
- 3.4.3 析構函數
- 3.4.4 拷貝語義
- 3.4.5 * 移動語義
- 3.5 友元
- 3.6 運算符重載與類型轉換
- 3.6.1 概述
- 3.6.2 重載方法
- 3.6.3 類型轉換
- 3.7 繼承與多態性
- 3.7.1 概述
- 3.7.2 派生類
- 3.7.3 子類型
- 3.7.4 虛基類
- 3.7.5 虛函數
- 3.7.6 抽象類
- 3.8 模板與泛型
- 3.8.1 概述
- 3.8.2 模板類型
- 3.8.3 *模板參數
- 3.8.4 *模板編譯
- 3.8.5 *模板推斷
- 3.8.6 *實例化與特例化
- 第4章 C++標準庫
- 4.1 概述
- 4.2 輸入輸出流
- 4.2.1 概述
- 4.2.2 *流的狀態
- 4.2.3 *常用流
- 4.2.4 *格式化I/O
- 4.2.5 *低級I/O
- 4.2.6 *隨機訪問
- 4.3 *C輸入輸出
- 4.3.1 *字符輸入輸出
- 4.3.2 *格式化輸入輸出
- 4.4 * 容器
- 4.4.1 * 概述
- 4.4.2 * 基本操作
- 4.4.3 * 順序容器
- 4.4.4 * 迭代器
- 4.4.5 * 容器適配器
- 4.5 * 泛型算法
- 4.6 * 內存管理
- 4.6.1 * 自動指針
- 4.7 * 其他設施