開始之前,先來看一個(gè)笑話,當(dāng)問一個(gè)c++程序員怎樣完成一個(gè)給定的任務(wù)時(shí),他(她)可能會(huì)提供一打或更多的潛在解決方案列表,但又會(huì)極其詳細(xì)地標(biāo)出每種方案的問題之處,讓你不知所措,難以選擇。而visual c++ 2005,通過c++/cli語(yǔ)言聯(lián)編,引入了泛型的概念,使c++程序員可進(jìn)一步提高程序的開發(fā)效率。關(guān)于 .net泛型與c++模板,盡管句法上很相似,但泛型與模板是以完全不同的方法實(shí)現(xiàn)的,它們之間沒有任何的內(nèi)置兼容性。 
  說到泛型與模板的差別,相信每個(gè) .net平臺(tái)的c++程序員都會(huì)問這個(gè)問題:我該選擇哪種技術(shù)呢?那些已用c++進(jìn)行了數(shù)年開發(fā)(特別是用visual c++)的人,相信早已知道答案:兩種技術(shù)都具有卓越的特性,但任何一者都不是另一者的超集,使用何種技術(shù)只限于給定的任務(wù),簡(jiǎn)而言之,沒有一種技術(shù)可以適用于所有情況下的解決方案。同樣,這種進(jìn)退兩難的狀況也折磨了visual c++程序員數(shù)年:win32或是mfc、atl或是wtl、com或是c風(fēng)格的dll、#import或是ccomptr。
  涉及 .net開發(fā)的c++知識(shí)
  在過去,visual c++利用某些技術(shù)手段,可使stl中的集合與其他技術(shù)協(xié)同工作,如在活動(dòng)模板庫(kù)(atl)中稱為ccomenuonstl的模板化類,它允許一個(gè)visual basic客戶端使用for each來枚舉由c++ com服務(wù)器提供的stl集合的內(nèi)容。雖然這種層次上的集成非常之淺,但在許多受限情況下證實(shí)非常有用?;谕瑯拥闹髦?,stl.net為c++程序員提供了標(biāo)準(zhǔn)stl庫(kù)的一種擴(kuò)展,這種擴(kuò)展可允許在一個(gè)c++/cli程序集內(nèi)部使用的stl集合,作為泛型集合暴露給其他的 .net程序集。
  stl.net提供了與標(biāo)準(zhǔn)stl集合相同的接口,因此,對(duì)熟悉標(biāo)準(zhǔn)stl集合與算法的c++程序員來說,不存在學(xué)習(xí)曲線。以visual c++ 2005來作說明,stl.net的頭文件位于cliext目錄中,如果要使用stl.net集合,例如vector,必須包含<cliext/vector>而不是標(biāo)準(zhǔn)的<vector>,另外,stl.net集合包含在cliext命名空間中,而不是標(biāo)準(zhǔn)stl集合所使用的std命名空間。
  注:visual c++開發(fā)小組仍在努力工作使stl.net變得更易使用,并提高它的性能。因?yàn)閟tl.net仍在不斷地進(jìn)行新的改進(jìn),本文將不會(huì)探討stl.net集合的過深之處,而會(huì)從一種更高的角度來看,為什么stl.net將會(huì)大有作為。
  橋接泛型與模板
  橋接泛型與模板這兩個(gè)不同的世界,實(shí)屬一項(xiàng)艱巨的任務(wù)。模板只是一個(gè)c++的概念,并只存在于編譯時(shí)期;然而,泛型是一個(gè) .net概念,它存在于已編譯的程序集中,并對(duì)所有 .net語(yǔ)言可用。stl.net所使用的解決方案是把類集當(dāng)作c++模板類來實(shí)現(xiàn),同時(shí)c++模板類也是 .net引用類型,并由其實(shí)現(xiàn)了icollection泛型接口。stl與stl.net中vector的聲明演示了這種設(shè)計(jì):
//stl vector 聲明
template<class _ty, class _ax = allocator<_ty> >
class vector;
//stl.net vector 聲明
template<typename _value_t>
ref class vector : generic::icollection<_value_t>
  在這兩者的聲明當(dāng)中,有一些關(guān)鍵的不同之處,除泛型接口的實(shí)現(xiàn)之外,stl.net vector并不能指定一個(gè)分配算符,只是簡(jiǎn)單地調(diào)用gcnew來分配一個(gè)新的所需元素。stl.net集合聲明時(shí)使用了ref關(guān)鍵字,這意味著它們都是 .net引用類型,將會(huì)被分配在 .net托管堆中。
  使用stl.net
  除去stl.net集合聲明時(shí)的一些差異(這個(gè)差異與c++/cli和標(biāo)準(zhǔn)c++間的句法差異有關(guān)),使用stl.net集合與stl集合基本上一模一樣。以下的控制臺(tái)示例程序聲明了一個(gè)vector對(duì)象,接著在集合中加入了一些其他不同類型的元素:
#include "stdafx.h"
#include <cliext/vector>
using namespace system;
using namespace cliext;
int main(array<system::string ^> ^args)
{
 vector<object^>^ v = gcnew vector<object^>;
 v->push_back(nullptr); //第一個(gè)元素為空
 v->push_back(gcnew object()); //第二個(gè)元素為一個(gè)純對(duì)象
 v->push_back(1); //第三個(gè)元素為裝箱的整數(shù)
 v->push_back("element four"); //第四個(gè)元素為字符串
 return 0;
}
  以上代碼演示了stl.net的一個(gè)重要特點(diǎn):仍舊是非常熟悉的集合類,另一個(gè)特點(diǎn)是,可在一個(gè)集合中使用兩種不同的編程模型,這意味著如果要查找上述代碼中的整數(shù)1,可使用下列stl find算法:
//當(dāng)作stl集合使用
bool containsonestl = find( v->begin( ), v->end( ), 1 ) != v->end();
  另外,.net中icollection泛型接口也能用于實(shí)現(xiàn)同樣的邏輯:
//當(dāng)作 .net集合使用
bool containsonedotnet = v->contains(1);
  這種可在同一集合類中同時(shí)使用stl和 .net算法的能力--而無須復(fù)制內(nèi)容或提供橋接函數(shù)--允許c++/cli程序員對(duì)任何有關(guān)集合的操作,選擇最恰當(dāng)?shù)暮瘮?shù)與庫(kù)。
  有關(guān)stl.net最后一個(gè)特點(diǎn)是,可為用c#或vb.net編寫的 .net程序集,無縫地提供其stl.net集合。由于stl.net集合實(shí)現(xiàn)了icollection泛型接口,所以在類型安全上,再無任何損耗,再者,stl.net集合使用了托管內(nèi)存來存儲(chǔ)集合中的元素,因此,在與那些提供stl.net集合的c++/cli程序集互操作時(shí),再無任何性能或代碼安全性方面的損耗。
  .net王國(guó)c++程序員的入場(chǎng)券
  stl.net代表了visual c++產(chǎn)品的一個(gè)重要部分,其允許c++程序員利用他們現(xiàn)有的技能與經(jīng)驗(yàn),盡早使用上帶成強(qiáng)大集合與算法的類庫(kù),而不至于被快速成長(zhǎng)的 .net世界拒之門外。
  stl.net作為一個(gè)光明的開端,將有助于c++在保持語(yǔ)言光榮傳統(tǒng)的同時(shí),成為 .net語(yǔ)言開發(fā)的第一類選擇。