C++/CLI可以說是標准語言一種新的"方言",它是Microsoft為充分利用CLI(Common Language Infrastructure)平台而開發出來的。那麼,它在語言方面有何新穎獨到之處呢,下面,就讓我們一起開始奇妙的C++/CLI語言之旅(文中所有示例代碼,均以Visual Studio.NET 2005 Professional編譯通過,所有的講解內容,也均以Visual Studio.NET 2005環境為基礎)。
程序集與元數據
傳統的C++編譯模式包括把單獨的源文件編譯為目標文件(obj),再把目標文件與庫函數鏈接在一起,以生成可執行程序。而CLI模式卻大不相同,它涉及到程序集的創建與使用。
簡單來說,在不計輸入源文件數目的基礎上,程序集即為單次編譯的輸出。如果輸出帶有一個進入點函數(例如main函數),它即為一個.exe文件;如果沒有,它則為一個.dll文件。任何引用外部程序集而生成的編譯,必須要訪問所依賴的程序集,此時也沒有類似傳統鏈接時用到的頭文件機制,而是通過編譯器在所依賴的程序集內部查找,來訪問所需的外部信息。
程序集包含了元數據,其描述了包含在那裡的類型與函數,還有CIL(Common Intermediate Language)指令--Microsoft稱其為"MSIL"。元數據與指令能通過獨立的VES(Virtual Execution System)來執行。
CLI類型
例1是一個模擬二維點的類。此處不得不提到命名空間,所有的CLI標准庫類型都屬於System命名空間,或嵌套在其內部的某個命名空間之下,例如System::Object和System::String,還有System::IO、 System::Text、System::Runtime::CompilerOptions等等。標記1可避免在程序中一直使用namespace限定詞。
例1:
/*1*/
using namespace System;
/*2*/
public ref class Point
{
int x;
int y;
public:
//定義用於讀寫X與Y實例屬性
/*3a*/ property int X
{
/*3b*/ int get() { return x; }
/*3c*/ void set(int val) { x = val; }
}
/*4a*/ property int Y
{
/*4b*/ int get() { return y; }
/*4c*/ void set(int val) { y = val; }
}
//定義實例構造函數
/*5a*/ Point()
{
/*5b*/ X = 0;
/*5c*/ Y = 0;
}
/*6a*/ Point(int xor, int yor)
{
/*6b*/ X = xor;
/*6c*/ Y = yor;
}
//定義實例方法
/*7a*/ void Move(int xor, int yor)
{
/*7b*/ X = xor;
/*7c*/ Y = yor;
}
/*8a*/ virtual bool Equals(Object^ obj) override
{
/*8b*/ if (obj == nullptr)
{
return false;
}
/*8c*/ if (this == obj) //我們在測試自己嗎?
{
return true;
}
/*8d*/ if (GetType() == obj->GetType())
{
/*8e*/ Point^ p = static_cast<Point^>(obj);
/*8f*/ return (X == p->X) && (Y == p->Y);
}
return false;
}
/*9*/ virtual int GetHashCode() override
{
return X ^ (Y << 1);
}
/*10a*/ virtual String^ ToString() override
{
/*10b*/ return String::Concat("(", X, ",", Y, ")");
}
};
在標記2中,我們定義了一個稱為Point的引用類(ref class),一個引用類是一個CLI引用類型,當兩者一起使用時,ref與class(中間有空格)表示了一個新的關鍵詞。