類函數(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