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