跳至內容

C++/CLI

維基教科書,自由的教學讀本
< C++

C++/CLI是微軟公司從Visual Studio 2005開始對C++既支持傳統的native C++,又支持.NET的managed編程的一種混合語言。

指針與句柄

[編輯]

C++的傳統指針照舊。

受管的類的對象,用句柄來引用到該對象。句柄賦值為空,必須用nullptr,不能用NULL。

句柄的寫法為 Object^ a1=nullptr; 注意這裡^讀作hat。

與傳統指針的&運算符對應,受管對象可以用%來獲得句柄值或者表示對句柄本身的應用。如 Object^ a1=%obj; void foo(Object^* a1); 這類似於C#的函數參數傳引用(用ref或out關鍵字)。

受管的struct和class

[編輯]

受管的struct和class,如果使用value關鍵字,則對應於C#的struct,在棧上存放;

受管的struct和class,如果使用ref關鍵字,則對應於C#的class,在受管堆上存放。

不能定義受管類型的全局變量或靜態變量,這跟C#保持一致。可定義為受管類的公開靜態數據成員。

受管類可以包含native指針類型,但native類不能包含受管類型的數據成員,因為GC難以跟蹤native對象的生命期。但可以用頭文件<msclr\gcroot.h>中的特殊智能指針類msclr::gcroot以在native類中包含受管類型的句柄。

受管類不能包含native類作為數據成員。native類不能包含值型的受管類作為數據成員。

融合傳統C++和C#對類的語法,受管類的語法特性:

  • 類繼承時,覆蓋的成員函數必須顯式寫overridden關鍵字或new關鍵字(表示在虛表中新建一個slot),並在派生類中必須顯式寫virtual關鍵字(傳統C++可不寫)。
  • interface class或者interface struct聲明了接口,兩種形式沒有差別。接口可以包含公開的函數、事件、屬性、靜態成員。成員函數僅聲明無定義。
  • 沒有實現全部基類或接口中的抽象函數的類自動就是抽象的。方法或者類可以顯式用abstract關鍵字指定為抽象的。抽象類不能實例化。
  • sealed關鍵字用於類或方法。
  • 用abstract sealed關鍵字指示為靜態類。
  • 受管類要求聲明早於使用,或者前向聲明。這跟傳統C++一樣。

受管類的析構器和終結器

[編輯]

析構器(destructor)和終結器(finalizer)適用於:

  • 類擁有一些資源,不能由垃圾回收GC來釋放,必須手工釋放,如native指針、需要調Close()方法的對象等。
  • 類擁有一些資源,需要不再使用時立即釋放,如打開的文件、網絡socket、資料庫連接等。

終結器聲明為!ClassName();,實際上覆蓋了Object::Finalize方法。垃圾回收該對象之前會自動調用Finalize方法。

析構器聲明為 ~ClassName();,等價實現了IDisposable接口和Dispose方法,並在其底部調用GC::SuppressFinalize方法。析構器就像C#中的Dispose方法,並不一定會被調用。因此要確保在終結器中做一切必須的清理工作。C++/CLI中通過 delete obj1;來調用析構器,這實際上調用了IDisposable::Dispose方法。調用析構器將抑制垃圾回收GC調用終結器。

C#中,IDisposable對象可用using(){}語法結構使得在結束該結構時Dispose方法被自動調用。C++/CLI等效機制必須把該受管對象定義為value,這樣在退出作用域時會被自動調用析構器。

桌面應用從.NET Framework遷移到.Net Core

[編輯]

因為C++/CLI一直使用非SDK風格的XML項目文件,所以需要手工遷移。要點:

  • 可能需要在x64下調試
  • 生成一個.Net Core的class library項目,與老的.NET Framework對比project文件(.vcxproj)異同。還必須更改包含Reference元素的<ItemGroup>,以使用單個<FrameworkReference>元素。包括:
    • <TargetFrameworkVersion>v4.X</TargetFrameworkVersion>改為<TargetFramework>netcoreapp3.1</TargetFramework>
    • 所有<CLRSupport>true</CLRSupport>改為<CLRSupport>NetCore</CLRSupport>
    • 刪除<Reference Include="System" /><Reference Include="System.Data" /><Reference Include="System.Windows.Forms" /><Reference Include="System.Xml" />
    • 如果使用Windows Forms APIs,增加<FrameworkReference Include="Microsoft.WindowsDesktop.App.WindowsForms" />;如果使用WPF API,增加<FrameworkReference Include="Microsoft.WindowsDesktop.App.WPF" />;如果同時使用Windows Forms和WPF APIs,增加<FrameworkReference Include="Microsoft.WindowsDesktop.App" />

C++/CLI在.NET上的限制

  • 不支持編輯為可執行程序,只能編譯為DLL.
  • C++/CLI只支持Windows上的.NET。
  • C++/CLI不能目標於.NET Standard.
  • C++/CLI項目不支持新的SDK風格的項目文件,只能跟其他Visual Studio C++項目使用一樣的.vcxproj文件格式。
  • C++/CLI項目不能目標於多個.NET平台。如果你要建造C++/CLI項目同時於.NET和.NET Framework,需要分開創建項目文件。
  • .NET不支持-clr:pure 或 -clr:safe編譯,只支持新的-clr:netcore編譯選項(等價於-clr之於.NET Framework)。