就在Borland C++ 3.1統(tǒng)治市場(chǎng)兩年以后,Microsoft憑借其當(dāng)仁不讓的霸氣和聞名的Visual C++系列產(chǎn)品逐漸奪回了Windows開發(fā)工具市場(chǎng)的主導(dǎo)權(quán)。與Borland不同的是,Visual C++中的MFC(Microsoft Foundation Class)框架庫(kù)沒有向OWL那樣肆意篡改C++的語法,而是采用了下面這樣的方式來實(shí)現(xiàn)消息映射(代碼取自MSDN示例程序):
// Example for BEGIN_MESSAGE_MAP BEGIN_MESSAGE_MAP( CMyWindow, CFrameWnd ) ON_WM_PAINT() ON_COMMAND( IDM_ABOUT, OnAbout ) END_MESSAGE_MAP( ) 事實(shí)上,用MFC框架編寫的C++代碼在大量使用宏定義等預(yù)編譯指令的同時(shí),還把WIN32平臺(tái)下常見的匈牙利風(fēng)格(有關(guān)標(biāo)識(shí)符大小寫和前綴的書寫規(guī)范)發(fā)揮到了極限。這一點(diǎn)用不著我多費(fèi)口舌,許多程序員僅從代碼的大小寫特征上就能百分之百地確定代碼中是否使用了MFC框架。
class ATL_NO_VTABLE CMyATLObj : public IMyATLObj, public ipersistStreamInitImpl <CMyATLObj>, public IOleControlImpl<CMyATLObj>, public IOleObjectImpl<CMyATLObj>, public IoleInPlaceActiveObjectImpl <CMyATLObj>, public IViewObjectExImpl<CMyATLObj>, public IoleInPlaceObjectWindowlessImpl <CMyATLObj>, public IPersistStorageImpl<CMyATLObj>, public IspecifyPropertyPagesImpl <CMyATLObj>, public IQuickActivateImpl<CMyATLObj>, public IDataObjectImpl<CMyATLObj>, public IProvideClassInfo2Impl <&__uuidof(CMyATLObj), NULL>, public CComControl<CMyATLObj> ...... 注重控件類CMyATLObj的代碼,CMyATLObj類居然是從N個(gè)接口類和控件類中派生出來的,類的聲明語句中隨處可見模板的身影——這就是Microsoft為我們?cè)O(shè)計(jì)的別具一格的ATL風(fēng)格的代碼了。之所以要不惜代價(jià)地大量使用模板、多重繼續(xù)等語言特性,這主要為了適應(yīng)COM、OLE、ActiveX等在架構(gòu)上本來就相對(duì)復(fù)雜的技術(shù)體系。但這樣一來,使用ATL的代碼在所有C++代碼中,就擁有了一副異乎平常的長(zhǎng)相了:到處都是尖括號(hào),到處都是以“I”打頭的標(biāo)識(shí)符,甚至還有多重尖括號(hào)的嵌套……假如要求一個(gè)剛學(xué)會(huì)C++語言的程序員馬上讀懂一大段ATL代碼,我想,用不了幾分鐘,他就會(huì)被代碼中那些晦澀、離奇的語言風(fēng)格折磨得精神崩潰了。
%:include <iostream> using namespace std; %:define MAX 5 void main() <% int m<:MAX:>; int i = 1; for (i = 0; i < MAX; i++) <% m<:i:> = i; if (i not_eq 3 and i < 5) cout << i << endl; %> %> 這是我自己編寫的一段代碼。你也許無法在Visual C++環(huán)境下運(yùn)行它,但它的語法的確符合1998年C++標(biāo)準(zhǔn)的規(guī)定。在GNU C++環(huán)境下,我曾成功地將其編譯為可執(zhí)行程序。
Borland公司在發(fā)布了Borland C++ 3.1之后,就因?yàn)椴凰歼M(jìn)取而將C++開發(fā)工具的市場(chǎng)拱手讓給了Microsoft[4]。在經(jīng)歷了Borland C++ 4.0、4.5和5.0等版本的失敗后,1997年,Borland推出了全新的C++開發(fā)工具C++Builder。這個(gè)在市場(chǎng)上為Borland挽回了顏面的產(chǎn)品不但在界面風(fēng)格上與Borland的支柱產(chǎn)品Delphi別無二致,甚至還在產(chǎn)品內(nèi)部直接照搬了Delphi的VCL(Visual Component Library)庫(kù)。結(jié)果,使用C++Builder開發(fā)的代碼天生就受到了Delphi風(fēng)格的傳染,長(zhǎng)相酷似Pascal語言了(以下代碼取自C++Builder 6.0的示例代碼):
class TFormClrDlg : public TForm { published: // IDE-managed Components TColorDialog *ColorDialog; TButton *Button; TPanel *Panel1; void fastcall ButtonClick(TObject *Sender); private: // User declarations public: // User declarations virtual fastcall TFormClrDlg(TComponent* Owner); }; 說實(shí)話,盡管C++Builder在市場(chǎng)上的表現(xiàn)不錯(cuò),但我還是不喜歡Borland將C++語言與Delphi中的Object Pascal語言刻意混淆的做法。也許在Borland這種做法的背后有提高產(chǎn)品通用性、縮短產(chǎn)品開發(fā)周期等體面的理由,但使用C++Builder開發(fā)出的代碼在外表上已經(jīng)離標(biāo)準(zhǔn)C++風(fēng)格越來越遠(yuǎn)了。
Microsoft將C++引入.NET環(huán)境的舉動(dòng)其實(shí)比Borland還要激進(jìn)。單從風(fēng)格上說,使用Visual C++ .NET開發(fā)的代碼可能兼具M(jìn)FC、ATL、標(biāo)準(zhǔn)C++、.NET托管代碼等多種不同的風(fēng)格。其中,對(duì)C++語言本身影響最大的,當(dāng)然要數(shù).NET托管代碼為C++注入的若干新鮮血液了:
#using <mscorlib.dll>
using namespace System; using namespace System::Reflection; using namespace System::Security::Permissions;
語言風(fēng)格的變遷從一個(gè)側(cè)面反映了技術(shù)思想和產(chǎn)業(yè)需求的嬗變規(guī)律。從1979年Stroustrup完成第一個(gè)Cpre預(yù)處理程序算起,C++語言來到這個(gè)世界上已經(jīng)快滿25個(gè)年頭了。這是一種在實(shí)踐中誕生、成長(zhǎng)和發(fā)展起來的語言。也許,Stroustrup從一開始就壓根兒也沒想把它設(shè)計(jì)成像Smalltalk那樣純粹的面向?qū)ο笳Z言。開放性、高效率、兼容性和擴(kuò)展性的需求將C++語言塑造成了一種典型的多模式(Multiparadigm)語言。無論是C++早期對(duì)Simula語言的繼續(xù),還是后來對(duì)Smalltalk、Ada、Clu等語言的借鑒,無論是ANSI/ISO標(biāo)準(zhǔn)風(fēng)格的迅速普及,還是Visual C++ .NET在技術(shù)創(chuàng)新上的不懈努力,所有這些歷史變遷都說明,C++在風(fēng)格上的多樣性主要源自C++語言本身“海納百川”的胸襟和氣概。