類函數是C++/CLI中引入的新概念,其功能類似于函數模板,但原理上卻迥然不同。使用函數模板時,編譯器根據模板生成函數源代碼,然后將其與其它代碼一起編譯。這種方法可能會產生許多函數,從而使得生成模塊的體積增加,這就是所謂的“代碼膨脹”。類函數與之不同,類函數本身將被編譯,在調用類函數時,實際類型在運行時取代了類函數的類型形參,這不會導致新增代碼的問題。

一、類函數的定義

類函數與普通函數的區別在于:它需要定義一個特殊的形參——類型形參,該參數說明在運行時傳遞給函數的參數類型。下面的例子定義了一個類函數,用于找出某種數據類型數組中最大的元素。

generic<typename T> where T:IComparable
T MaxElement(array<T>^ x)
{
	T max = x[0];
	for(int i=1; i<x->Lenght; i++)
		if(max->CompareTo(x[i])<0)
			max = x[i];
	return max;
}

關鍵字generic規定后面的內容為類函數定義,尖括號內用關鍵字typename定義了一個類型形參T,如果有多個類型形參,它們都放在尖括號內,用逗號分開。

關鍵字where引入使用類函數時,傳遞給T的類型實參應滿足的約束條件。這里的條件是:所有用于替代T的類型必須實現了IComparable接口。該約束也意味著,所有傳入的類型實參都實現了CompareTo()函數,允許對該類型兩個對象進行比較。

第二行定義了函數的返回值類型、函數名稱以及形參,與普通函數定義類似,但有的類型用T來描述,它們將在運行時被確定。

二、使用類函數

調用類函數的方法與調用普通函數的方法一樣。對上面聲明的MaxElement()函數可如此調用:

array<double>^ data = {1.5, 3.5, 6.7, 4.2, 2.1};
double maxData = MaxElement(data);

 在這個例子中,編譯器能夠判斷出該類函數的類型實參為double,生成調用函數的代碼(并非是該類函數的double版),執行時再用 double代替T。注意:與函數模板不同,對于類函數編譯器不創建函數實例,而是僅僅是使編譯后的代碼可以接受數據類型作為類型實參,實際的類型替換在運行時實現。

應該注意的是,如果以字符串常量作為實參傳遞給類函數,編譯器將認為類型實參是String^,無論該字符串常量是窄字符串(“Hello”)還是寬字符串(L“Hello”)。

有些情況下,編譯器無法根據函數調用來判斷類型實參是什么,這時可用在函數名后面加尖括號和類型名稱來顯示的指定,上面的例子也可以寫作

double maxData = MaxElement<double>(data);

另外需要注意的是,提供給類函數作為類型實參的不能是本地C++類型、本地指針、引用,也不能是值類類型的句柄(如 int^)。而只能是值類型(如int、double)或引用類型的跟蹤句柄(如String^)。

下面是一個使用類函數的完整示例。

- - - - - - - - - - - - - - - - <<== 華麗的分割線 ::開始==>> [Ex6_10.cpp] - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// Ex6_10.cpp : main project file.
// Defining and using generic fuctions
#include "stdafx.h"

using namespace System;

// Generic function to find the maximum element in an array
generic<typename T> where T:IComparable
T MaxElement(array<T>^ x)
{
	T max = x[0];
	for(int i=1; i<x->Length; i++)
		if(max->CompareTo(x[i])<0)
			max = x[i];
	return max;
}

// Generic function to remove an element from an array
generic<typename T> where T:IComparable
array<T>^ RemoveElement(T element, array<T>^ data)
{
	array<T>^ newData = gcnew array<T>(data->Length-1);
	int Index = 0;		// Index to elements in newData array
	bool found = false;	// Indicates that the element to remove from was found
	for each(T item in data)
	{
		// Check for invalid index or element found
		if((!found) && item->CompareTo(element)==0 )
		{ 
			found = true;
			continue;
		}
		else
		{
			if(Index == newData->Length)
			{
				Console::WriteLine(L"Element to remove not found");
				return data;
			}
			newData[Index++] = item;
		}
	}
	return newData;
}

// Generic function to list an array
generic<typename T> where T:IComparable
void ListElements(array<T>^ data)
{
	for each(T item in data)
		Console::Write(L"{0, 10}", item);
	Console::WriteLine();
}

int main(array<System::String ^> ^args)
{
	array<double>^ data = {1.5, 3.5, 6.7, 4.2, 2.1};
	Console::WriteLine(L"Array contains:");
	ListElements(data);
	Console::WriteLine(L"\nMaximun element = {0}\n", MaxElement(data));
	array<double>^ result = RemoveElement(MaxElement(data), data);
	Console::WriteLine(L"After removing maximun, array contains:");
	ListElements(result);


	array<int>^ numbers = {3, 12, 7, 0, 10, 11};
	Console::WriteLine(L"Array contains:");
	ListElements(numbers);
	Console::WriteLine(L"\nMaximun element = {0}\n", MaxElement(numbers));
	Console::WriteLine(L"After removing maximun, array contains:");
	ListElements(RemoveElement(MaxElement(numbers), numbers));

	array<String^>^ strings = {L"Many", L"hands", L"make", L"light", L"work"};
	Console::WriteLine(L"Array contains:");
	ListElements(strings);
	Console::WriteLine(L"\nMaximun element = {0}\n", MaxElement(strings));
	Console::WriteLine(L"After removing maximun, array contains:");
	ListElements(RemoveElement(MaxElement(strings), strings));

	return 0;
}
- - - - - - - - - - - - - - - - <<== 華麗的分割線 ::結束==>> [Ex6_10.cpp] - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

輸出如下

Array contains:
       1.5       3.5       6.7       4.2       2.1

Maximun element = 6.7

After removing maximun, array contains:
       1.5       3.5       4.2       2.1
Array contains:
         3        12         7         0        10        11

Maximun element = 12

After removing maximun, array contains:
         3         7         0        10        11
Array contains:
      Many     hands      make     light      work

Maximun element = work

After removing maximun, array contains:
      Many     hands      make     light