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)。