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

一、類函數(shù)的定義

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

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;
}

關(guān)鍵字generic規(guī)定后面的內(nèi)容為類函數(shù)定義,尖括號(hào)內(nèi)用關(guān)鍵字typename定義了一個(gè)類型形參T,如果有多個(gè)類型形參,它們都放在尖括號(hào)內(nèi),用逗號(hào)分開。

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

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

二、使用類函數(shù)

調(diào)用類函數(shù)的方法與調(diào)用普通函數(shù)的方法一樣。對(duì)上面聲明的MaxElement()函數(shù)可如此調(diào)用:

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

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

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

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

double maxData = MaxElement<double>(data);

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

下面是一個(gè)使用類函數(shù)的完整示例。

- - - - - - - - - - - - - - - - <<== 華麗的分割線 ::開始==>> [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;
}
- - - - - - - - - - - - - - - - <<== 華麗的分割線 ::結(jié)束==>> [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