文章目錄
- 一、類模板使用流程
- 1、類模板 定義流程
- 2、類模板 使用
- 3、類模板 函數 外部實現
- 二、類模板 static 關鍵字
- 1、類模板 static 靜態成員
- 2、類模板 static 關鍵字 用法
- 3、完整代碼示例
將 類模板 函數聲明 與 函數實現 分開進行編碼 , 有 三種 方式 :
- 類模板 的 函數聲明 與 函數實現 都寫在同一個類中 , 也就是沒有分開進行編碼 ;
- 類模板 的 函數實現 在 類外部進行 , 函數聲明 和 實現 寫在相同的 .cpp 源碼文件中 ;
- 類模板 的 函數實現 在 類外部進行 , 函數聲明 和 實現 寫在不同的 .h 和 .cpp 源碼文件中 ;
在博客 【C++】泛型編程 ⑨ ( 類模板的運算符重載 - 函數聲明 和 函數實現 寫在同一個類中 | 類模板 的 外部友元函數問題 ) 中實現了第一種情況 , 類模板 的 函數聲明 與 函數實現 都寫在同一個類中 , 也就是沒有分開進行編碼 ;
在博客 【C++】泛型編程 ⑩ ( 類模板的運算符重載 - 函數實現 寫在類外部的同一個 cpp 代碼中 | 類模板 的 外部友元函數二次編譯問題 ) 中 , 分析了 第二種情況 , 類模板 的 函數實現 在 類外部進行 , 寫在 一個 cpp 源碼文件中 ;
在博客 【C++】泛型編程 ? ( 類模板的運算符重載 - 函數實現 寫在類外部的不同的 .h 頭文件和 .cpp 代碼中 ) 中 , 分析 第三種 情況 , 函數實現 在 類外部進行 , 函數聲明 和 實現 寫在不同的 .h 和 .cpp 源碼文件中 ;
一、類模板使用流程
1、類模板 定義流程
類模板 定義流程 :
- 首先 , 定義一個 使用 實際數據類型 的類 , 這里的數據類型 指的是 成員變量類型 或 成員函數 參數或返回值 類型 ; 這些類型 由于是 實際類型 , 語義明確 , 含義清楚 , 不會報錯 ;
- 然后 , 將 要使用 泛型模板 的 類型 , 改為一個 自己定義的 虛擬泛型類型 , 如 :
template <typename T>
中的 T 類型 ; - 最后 , 在 類聲明 前面加上
template <typename T>
, 其中的 T 類型可以改為其它字母代替 , 一般是大寫字母 ;
2、類模板 使用
使用類模板 : 使用 類模板 創建實例對象時 , 首先要注明 具體類型 , 生成具體類 , 才能創建具體類的 實例對象 , 語法格式如下 ;
類模板名稱<實際類型名稱> 對象名稱;
類模板名稱<實際類型名稱> 對象名稱(構造函數實參列表);
以 上一篇博客的 Student 類模板為例 , 創建 Student 類模板實例對象示例如下 ;
Student<int> s;
Student<int> s(1, 2);
3、類模板 函數 外部實現
如果要在 類模板 之外 實現 類模板中的 成員函數 ,
首先 , 要 聲明 類模板 的類型參數 ;
template <typename 類型參數列表>
然后 , 使用 域操作符 :: 訪問類模板中的函數 , 訪問時需要 注明 類模板的 實際參數類型 ;
函數返回值類型 類模板名稱<實際參數類型列表>::成員函數名(函數形參列表)
{
}
特別注意 , 如果上面的類型中 , 涉及到的 函數返回值類型 或 函數形參列表 中 , 有 類模板類型 , 也要注明 實際的參數類型 ;
如下面的 operator+ 函數 ,
template <typename T>
class Student
{
public:// 重載 + 運算符Student operator+(Student& s);
};
在 類模板 外部 實現上述 函數聲明 , 就需要使用如下方式 ;
// 重載 + 運算符
// 使用 Student<T>:: 域操作符訪問函數
template <typename T>
Student<T> Student<T>::operator+(Student<T>& s)
{// 函數內部的類的 <T> 模板類型 , 可加 Student<T> 可不加 Student// 不加 <T> 也可以使用 , 加了也不會報錯Student student(this->a + s.a, this->b + s.b);return student;
}
二、類模板 static 關鍵字
1、類模板 static 靜態成員
類模板中 , 定義了 static 靜態成員變量 ;
靜態 成員變量 是屬于整個類的 , 但是對于 類模板 來說 , 存在著二次編譯 , 會生成多個不同的實際類 ;
類模板 的 實際類型 可能有多種 , 如 Student<int>
和 Student<double>
是兩個具體的實際類型 , C++ 編譯器會將 類模板 編譯成 兩個不同的 類 ;
上述 編譯成的 不同的類 , 每個類 都有一個 static 靜態成員 , 相互之間是獨立的 ;
2、類模板 static 關鍵字 用法
類模板 static 關鍵字 用法 :
首先 , 在 類模板 中 , 聲明 static 靜態成員 ;
template <typename T>
class Student
{
public:// 類模板中的靜態成員static T m_a;
};
然后 , 在類外部 , 初始化靜態成員 , 之后才能 使用該靜態成員 , 使用 靜態成員 時 , 要聲明 類模板 類型 template <typename T>
, 下面使用 域作用符 訪問時 , 需要注明 類模板類型 ;
// 初始化靜態成員
template <typename T>
T Student<T>::m_a = 0;
最后 , 使用 類模板 中的靜態成員時 , 每個 生成的 具體類型 , 都有一個獨立互不干擾的 靜態成員 ; 下面 Student<int>
類型的對象 s1 , s2 共享 靜態成員 m_a , Student<double>
類型的對象 s3 , s4 共享 靜態成員 m_a ; s1 和 s3 是不同的靜態成員 ;
Student<int> s1, s2;
Student<double> s3, s4;
3、完整代碼示例
代碼示例 :
#include "iostream"
using namespace std;template <typename T>
class Student
{
public:// 類模板中的靜態成員static T m_a;
};// 初始化靜態成員
template <typename T>
T Student<T>::m_a = 0;int main() {Student<int> s1, s2;cout << "s1, s2 賦值前 : s1.m_a : " << s1.m_a << " , s2.m_a : " << s2.m_a << endl;s1.m_a = 6;cout << "s1, s2 賦值后 : s1.m_a : " << s1.m_a << " , s2.m_a : " << s2.m_a << endl;Student<double> s3, s4;cout << "s3, s4 賦值前 : s3.m_a : " << s3.m_a << " , s4.m_a : " << s4.m_a << endl;s3.m_a = 8;cout << "s3, s4 賦值后 : s1.m_a : " << s1.m_a << " , s2.m_a : " << s2.m_a << endl;cout << "s3, s4 賦值后 : s3.m_a : " << s3.m_a << " , s4.m_a : " << s4.m_a << endl;// 控制臺暫停 , 按任意鍵繼續向后執行system("pause");return 0;
}
執行結果 :
s1, s2 賦值前 : s1.m_a : 0 , s2.m_a : 0
s1, s2 賦值后 : s1.m_a : 6 , s2.m_a : 6
s3, s4 賦值前 : s3.m_a : 0 , s4.m_a : 0
s3, s4 賦值后 : s1.m_a : 6 , s2.m_a : 6
s3, s4 賦值后 : s3.m_a : 8 , s4.m_a : 8
請按任意鍵繼續. . .