C++/CLI 獨特地支援堆疊語意的參考型別實例與追蹤參考(tracking reference),填補了本地 C++ 物件模型與 CLI 記憶體管理的鴻溝。本文深入解析這兩大機制及其對拷貝建構、指派、相等性比較的影響。
宣告語法如同值型別,但實際為參考型別:
Point p1; // 預設建構
Point p2(3, 4); // 引數建構
特性:
static 或全域實例sizeof(p1) 編譯錯誤(大小執行期才定),但 sizeof(Point^) 合法%對應本地 C++ 的 &,但能追蹤 GC 移動的物件:
Point^ hp = gcnew Point(2,5);
Point% p4 = *hp; // 追蹤 hp 參考的物件
Point% p5 = *gcnew Point(2,5); // 追蹤臨時物件
% 僅限自動儲存期(區域變數)%,必須用 &% 之於 ^,如同 & 之於 *&)System::String 和 array<T> 的控制代碼不能用 * 解參考。
% (一元)將堆疊語意實例轉為控制代碼:
Point p1;
Console::WriteLine("p1 is {0}", %p1); // %p1 型別為 Point^ → 隱式轉 Object^
C++/CLI 標準新增術語:gc-lvalue = 參考 CLI 堆中物件、或包含該物件資料成員的運算式。
*h (h 為 handle) → gc-lvalue%h → gc-lvalue參考型別不提供預設拷貝建構/指派(基類 Object 無此成員)。需手動實作:
Point(Point% p) { // 使用追蹤參考
X = p.X;
Y = p.Y;
}
對比本地 C++:Point(const Point& p)。參考型別無 const 語意。
Point% operator=(Point% p) {
X = p.X;
Y = p.Y;
return *this; // 回傳追蹤參考
}
static bool operator==(Point% p1, Point% p2) {
if (p1.GetType() == p2.GetType()) {
return (p1.X == p2.X) && (p1.Y == p2.Y);
}
return false;
}
nullptr,無需檢查. 而非 -> 存取成員| 需求 | C++/CLI 開發者期望 | C#/VB.NET 開發者期望 |
|---|---|---|
| 物件複製 | 拷貝建構、指派運算子 | Clone()、ICloneable |
| 相等比較 | ==/!= 運算子 | Equals() |
| 參考語意 | 堆疊語意、追蹤參考 | 純控制代碼 (^) |
Equals(Object^) 覆寫(跨語言通用)operator==(T%, T%)(追蹤參考版)operator==(T^, T^)(語意模糊:比較參考還是值?)System::String 例外:提供 ==(String^, String^) 比較值this 指標型別差異this 型別為 T^this 型別為 interior_ptr<T>const 在 CLI 型別中的處理const/volatilethis 型別為 R^(非 R* const)const,但控制代碼值不可修改ToString 格式化
// 字串連接
return String::Concat("(", X, ",", Y, ")");
// 格式化(支援對齊、精度等)
return String::Format("({0},{1})", X, Y);
#if defined(__cplusplus_cli) && __cplusplus_cli == 200406L
// 支援 C++/CLI
#endif
System::Decimal 高精度金融計算
Decimal x = Decimal::Parse("23.00"); // scale=2
Decimal y = Decimal::Parse("2.000"); // scale=3
Decimal result = x * y + Decimal::Parse("2.5"); // scale=5
Console::WriteLine(result); // 48.50000
scale 屬性保留小數位數(含尾數 0)__identifier
// 其他語言定義的類別有名為 delete 的 public 成員
ref class X { public: static void delete(); };
// C++/CLI 呼叫
X::__identifier(delete)(); // 避開 C++ delete 關鍵字
literal 編譯期常數
literal double PI = 3.1415926;
literal int MinValue = -10, MaxValue = 10;
literal int Range = MaxValue - MinValue + 1; // 編譯期計算
literal String^ Title = "Annual Report"; // 唯一允許的控制代碼常值
static const 但不可標記 staticenum、字串常值、nullptr堆疊語意實例與追蹤參考是 C++/CLI 連結本地 C++ 習慣與 CLI 記憶體模型的關鍵橋樑。正確實作拷貝/指派/相等性、理解 this 型別差異、提供雙重介面(Equals + operator==)、善用 Decimal/literal/__identifier,能撰寫高效能、跨語言互操作性佳的 CLI 程式庫。