C++中類模板的概念和意義


1,在 C++ 中是否能夠將泛型的思想應用於類?

    1,函數模板是將泛型編程的思想應用於函數,就有了函數模板;

    2,可以,常用的 C++ 標准庫就是 C++ 中的標准模板庫,C++ 中的 STL 就是將泛型的思想應用於一系列的函數,就得到了函數模板,當然也有很多的類模板;

    3,類模板就是將泛型思想應用於 C++ 中的類而得到的新概念;

 

2,類模板:

    1,一些類主要用於存儲和組織數據元素;

       1,類模板就是為了數據結構而誕生的;

    2,類中數據組織的方式和數據元素的 具體類型無關;

    3,如:數組類、鏈表類、Stack 類、Queue 類等;

       1,C++ 中將模板的思想應用於類,使得類的實現不關注數據元素的具體類型,而只關注類所需實現的功能;

      

3,C++ 中的類模板:

    1,以相同的方式處理不同的類型;

    2,在類聲明前使用 template 進行標識;

    3,< typename T > 用於說明類中使用的泛指類型 T;

       1,代碼示例:

1 template < typename T >
2 class Operator  // class 表明將泛型編程應用於類
3 {
4 public:
5     T op(T a, T b)  // T 在使用類模板定義具體對象的時候關心,其它時候不關心;
6 };

    4,類模板的應用:

       1,只能顯示指定具體類型,無法自動推導;

       2,使用具體類型 < Type > 定義對象;

           1,代碼示例:

1 Operator<int> op1;
2 Operator<string> op2;
3  int i = op1.op(1, 20);
4 string s = op2.op("D.T.", "Software");

             

4,類模板:

    1,聲明的泛指類型 T 可以出現在類模板的任意地方;

    2,編譯器對類模板的處理方式和函數模板相同;

       1,從類模板通過具體類型產生不同的類;

           1,編譯器將類模板當做一個模子,這個模子可以產生許多實實在在的類;

       2,在聲明的地方對類模板代碼本身進行編譯;

       3,在使用的地方對參數替換后的代碼進行編譯;

      

5,類模板初探編程實驗:

 1 #include <iostream>
 2 #include <string>
 3 
 4 using namespace std;
 5 
 6 template < typename T >
 7 class Operator  // 要是用這個類模板有一個前提條件,即當前的 Operator 類模板要操作的數據類型必須支持 +、-、*、/ 這四個運算符,這四個運算符如果要運用於自己定義的數據類型類,要重載這四個運算符;第一次編譯是對類模板本身的語法進行編譯;
 8 {
 9 public:
10     T add(T a, T b)
11     {
12         return a + b;
13     }
14     
15     T minus(T a, T b)
16     {
17         return a - b;
18     }
19     
20     T multiply(T a, T b)
21     {
22         return a * b;
23     }
24     
25     T divide(T a, T b)
26     {
27         return a / b;
28     }
29 };
30 
31 string operator-(string& l, string& r)  // 全局函數方式重載 - 操作符,編譯通過;先類內部、再全局
32 {
33     return "Minus";  // 僅僅為了說明問題;
34 }
35 
36 int main()
37 {
38     Operator<int> op1;
39     
40     cout << op1.add(1, 2) << endl;  // 3;
41     
42     Operator<string> op2;  // 第二次使用類模板時進行編譯,但是並不是對所有模板中的函數進行了第二次編譯,是分步編譯的,首先編譯的是構造函數,此時用的是默認的,沒有問題,這里編譯通過;
43     
44     cout << op2.add("D.T.", "Software") << endl;  // D.T.Software;這里編譯器針對 add() 函數進行第二次編譯;
45     cout << op2.minus("D.T", "Software") << endl;  // 未有定義全局的重載 - 操作符的函數時,字符串相減沒有定義,報錯;這里報錯展示出來是為了證明類模板編譯也是經過了兩次編譯;這里編譯器針對 minus() 函數進行第二次編譯;定義全局的重載 - 操作符函數后,打印 Minus ;
46     
47     return 0;
48 }

    1,編譯器對類模板第一次編譯針對類模板本身代碼進行編譯;

    2,第二次編譯是使用類模板時針對每個成員函數獨立編譯;

   

6,類模板的工程應用:

    1,類模板必須在頭文件中定義;

    2,類模板不能分開實現在不同的文件中;

    3,類模板外部定義的成員函數需要加上模板 <> 聲明;

       1,將類模板的成員函數實現放到類模板的外部實現;

       2,以上三條規則不是 C++ 和編譯器的一部分,只是工程應用里習慣這樣做,這樣做后,代碼可維護性、擴展性都會變好,因此建議遵守這三條規則;

 

7,模板類的工程應用編程實驗:

    1,頭文件(名字和類名一樣) Operator.h 中的內容:

 1 #ifndef _OPERATOR_H_  // 防止被包含兩次;
 2 #define _OPERATOR_H_
 3 
 4 template < typename T >
 5 class Operator
 6 {
 7 public:
 8     T add(T a, T b);
 9     T minus(T a, T b);
10     T multiply(T a, T b);
11     T divide(T a, T b);
12 };
13 
14 template < typename T >  // 加上類模板;
15 T Operator<T>::add(T a, T b)  // add() 是 Operator 類模板的;
16 {
17     return a + b;
18 }
19 
20 template < typename T >
21 T Operator<T>::minus(T a, T b)
22 {
23     return a - b;
24 }
25 
26 template < typename T >
27 T Operator<T>::multiply(T a, T b)
28 {
29     return a * b;
30 }
31 
32 template < typename T >
33 T Operator<T>::divide(T a, T b)
34 {
35     return a / b;
36 }
37 
38 #endif

 2,頭文件的應用;

 1 #include <iostream>
 2 #include <string>
 3 #include "Operator.h"
 4 
 5 using namespace std;
 6 
 7 int main()
 8 {
 9     Operator<int> op1;
10     
11     cout << op1.add(1, 2) << endl;  // 3;
12     cout << op1.multiply(4, 5) << endl;  // 20;
13     cout << op1.minus(5, 6) << endl;  // -1;
14     cout << op1.divide(10, 5) << endl;  // 2;
15     
16     return 0;
17 }

      1,三條規則不是硬性要求但是卻可以帶來很大好處;

   

8,小結:

    1,泛型編程的思想可以應用於類;

    2,類模板以相同的方式處理不同類型的數據;

    3,類模板非常適用於編寫數據結構相關的代碼;

    4,類模板在使用時只能顯示指定類型;


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM