C++/CLI
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)。