1. 程式人生 > >C++中的類模板

C++中的類模板

類模板(class template是用來生成類的藍圖,它使類中的一些成員變數和成員函式的引數或返回值可以取任意的資料型別。

1 類模板的宣告

類模板通過關鍵字template來定義,其宣告格式為

template <模板引數列表>

class 類名

{

   //使用模板引數

}

其中,模板引數列表的格式為typename 引數1, typename 引數2,...”,其中typename可以用class代替。

如下,定義了一個類模板

template<typename T>
class MyClass
{
public:
    T FindMax(T x1, T x2);
}

2 類模板成員函式的定義

類模板的成員函式可以在類模板內部定義,也可以在類模板的外部定義。

2.1 在類模板內部定義

在類模板MyClass中定義一個名為FindMax()的成員函式,該成員函式的作用是返回兩個數的最大值。

MyClass類模板定義的內部,有如下函式

T FindMax(T x1, T x2)
{
if(x1>=x2)
   return x1;
else
   return x2;
}

2.2 在類模板外部定義

在類模板外部定義成員函式時,需要加入template關鍵字。其定義格式為

template<模板引數列表>

返回值 類名<模板引數表>::

成員函式名(函式引數列表)

{

   //成員函式內容;

}

假設類模板MyClass如“1 類模板的宣告”中的格式,此時在MyClass類模板的外部定義FindMax()成員函式。

template<typename T>
T MyClass<T>::FindMax(T x1, T x2)
{
if(x1>=x2)
   return x1;
else
   return x2;
}

3 類模板的例項化

在定義類模板的物件時,必須指定模板引數的實參。

MyClass<int> myclass;
int max = myclass.FindMax(1, 2);
其中,將類模板的引數指定為int型別,則此時定義的myclass是類模板MyClassint版本。

4 在類模板中使用類中自定義的型別

假設T是一個類模板的模板引數,當編譯器遇到類似T::size_type這樣的程式碼時,它不會知道size_type是一個自定義的型別還是類的靜態成員變數,直到例項化時才會知道。例如,在類模板的某個成員函式中有如下程式碼

template<typename T>
void MyClass<T>::MyFunc()
{
T::size_type* pszit_type;
}
此時,如果將size_type看作是類的靜態成員變數,則以上語句為size_type乘以psize_type;而如果將size_type看作是類自定義的型別,則以上語句的作用是聲明瞭一個size_type的指標pszit_type

在預設情況下,C++編譯器認為是第一種情況,即將size_type看作是類的靜態成員變數。如果希望C++編譯器將size_type看作是類自定義的型別,則需要顯式地告訴編譯器該名字是一個型別,通過typename來實現這一點:

template<typename T>
void MyClass<T>::MyFunc()
{
typename T::size_type* pszit_type;
}

5 應用

MSDN論壇上,有朋友給出如下程式碼

#include "stdafx.h"
#include<iostream>
#include<cstdio>
#include<cstdlib>
using namespace std;
template<typename T>
class MyClass
{
public:
struct MyStruct
{
T x;
};
MyStruct doo(T temp);
};
template<typename T>
MyClass<T>::MyStruct
MyClass<T>::doo(T temp)
{
MyStruct tp;
tp.x = temp;
cout << "yes";
return tp;
};
int main()
{
MyClass<int> cls;
cout << cls.doo(3).x;
system("pause");
 
return 0;
}
以上程式碼定義了一個類模板MyClass,在該類模板中又定義了一個名為doo()的成員函式,該成員函式的返回值是MyClass類中自定義的MyStruct類,並且doo()成員函式是在MyClass的外部進行定義的。

VS2015中編譯該程式碼,給出的錯誤提示是

 warning C4346: “MyStruct”: 依賴名稱不是型別

error C2061: 語法錯誤: 識別符號“MyStruct”

正如4 在類模板中使用類中自定義的型別”中提到的,在定義doo()成員函式時,C++編譯器將該函式的返回值MyClass<T>::MyStruct當作了MyClass類中的成員變數,所以會有以上的錯誤提示。

那麼修改的方法就是在MyClass<T>::MyStruct之前加入typename以提示C++編譯器MyStruct是一個型別而不是變數。

template<typename T>
typename MyClass<T>::MyStruct
MyClass<T>::doo(T temp)
{
 .....
}