将程序从托管扩展 C++ 迁移到 C++/CLI(1)

3/8/2008来源:C/C++教程人气:6566

简介   C++/CLI代表 ISO-C++标准语言的一个动态编程泛型扩展 (dynamic PRogramming paradigm extension)。在原版语言设计 (V1) 中有许多显著的弱点,我们觉得在修订版语言设计 (V2) 中已经修正了这些弱点。本文列举了 V1 版本语言的功能和它们在 V2 版本中的对应功能(假如存在);并指出了其对应功能不存在的构造。对于有爱好的读者,可以查看附录中提供新语言设计的扩展原理。另外,一个源代码级别的转换工具 (mscfront) 正在开发中,而且可能在 C++/CLI的发布版中提供给希望将 V1 代码自动移植到新语言设计的人。   本文分为五个章节加一个附录。第一节讨论语言要害字的主要问题,非凡是双下划线的移除以及与上下文相关和由空格分隔的要害字。第二节着眼于托管类型的变化 — 非凡是托管引用类型和数组。还可以在这里找到有关确定性终结语义 (deterministic finalization) 的具体讨论。关于类成员的变化,例如属性、索引属性和操作符,是第三节的重点。第四节着眼于 CLI 枚举、内部和钉住指针的语法变化。它也讨论了许多可观的语义变化,例如隐式装箱的引入、CLI枚举的变化,和对值类中默认构造函数的支持的移除。第五节有点像大杂烩 — 乱七八糟的杂项。讨论了类型转换符号、字符串字符的行为和参数数组。   1. 语言要害字   原版到修订版语言设计的一个重要转换是在所有要害字中去掉双下划线。举例来说,一个属性现在被声明为 property而不是 __property。在原版语言设计中使用双下划线前缀的两个主要原因是:   1. 这是提供符合 ISO-C++标准的本地扩展的一致性方法。原版语言设计的一个主要目标就是不引入与标准语言的不兼容性,例如新的要害字和标记。这个原因很大程度上也推动了对声明托管引用类型的对象的指针语法的选择。 2. 双下划线的使用,除了兼容性方面的原因之外,也是一个不会对有旧代码基础的用户造成影响的合理保证。这是原版语言设计的第二主要目标。   这样的话,为什么我们移除双下划线(并且引入了一些新的标记)?不是的,这并不代表我们不再考虑和标准保持一致!   我们继续致力于和标准一致。尽管如此,我们意识到对 CLI动态对象模型的支持表现出了一种全新的强大的编程范型。我们在原版语言设计上的经验以及设计与发展 C++ 语言本身的经验使我们确信,对这个新范型的支持需要它自己的高级要害字和标记。我们想提供一个该新范型的一流表达方式,整合它并且支持标准语言。我们希望您会感受到修订版语言设计提供了对这两种截然不同的对象模型的一流的编程体验。   类似的,我们很关心最小化这些新的要害字的对现有代码可能造成的冲击。这是用与上下文相关和由空格分隔的要害字来解决的。在我们着眼于实际语言语法的修订之前,让我们试试搞清楚这两个非凡要害字的特点。   一个与上下文相关的要害字在特定的程序上下文中有非凡的含义。例如,在通常的程序中,sealed 是一个普通标识符。但是,在一个托管引用类类型的声明部分,它就是类声明上下文中的一个要害字。这使得在语言中引入一个新的要害字的潜在影响降到最低程度,我们认为,这对已经拥有代码基的用户非常重要。同时,它答应新功能的使用者获得一流的新增语言功能的体验 — 我们认为在原版语言设计中缺少这些因素。我们将在 2.1.2节中看到 sealed用法的示例。   一个由空格分隔的要害字是与上下文相关要害字的特例。它在字面上将一个与上下文相关的修饰符和一个现存的要害字配对,用空格分隔。这个配对作为一个单独的单位,例如 value class(示例参见 1.1 节),而不是两个单独的要害字。基于现实的因素,这意味着一个重新定义 value 的宏,如下所示:      #ifndef __cplusplus_cli    #define value 不会在一个类声明中去掉 value。假如确实要这么做的话,必须重新定义单元对,编写如下代码:      #ifndef __cplusplus_cli 考虑到现实的因素,这是十分必要的。否则,现存的 #define可能转换由空格分隔的要害字的与上下文相关的要害字部分。  2.托管类型
声明托管类型和创建以及使用这些类型的对象的语法已经大加修改,以提高 ISO-C++类型系统内的集成性。这些更改在后面的小节中详述。委托的讨论延后到 2.3节以用类中的事件成员表述它们 — 这是第 2 节的主题。(有关更加具体的跟踪引用语法介绍的内幕和设计上的主要转变的讨论,请参见附录A:推动修订版语言设计。)

2.1 声明一个托管类类型

在原版语言定义中,一个引用类类型以 __gc要害字开头。在修订版语言中,__gc要害字被两个由空格分隔的要害字 ref class或者 ref strUCt之一替代。struct或者 class的选择只是指明在类型体中开头未标记部分声明的其成员的公共(对于 struct)或者私有(对于 class)默认访问级别。 类似地,在原版语言定义中,一个 value 类类型以 __value 要害字开头。在修订版语言中,__value 要害字被两个由空格分隔的要害字 value class或者 value struct之一代替。 在原版语言设计中,一个接口类型是用要害字 __interface指明的。在修订版语言中,它被 interface class替代。 例如,下列类声明对   // 原版语法     public __gc class Block { ... };   // 引用类    public __value class Vector { ... };   // 值类    public __interface IMyFile { ... };   // 接口类 在修订版语言设计下等价的声明如下:    // 修订版语法     public ref class Block { ... };    public value class Vector { ... };    public interface class IMyFile { ... }; 选择 ref(对于引用类型)而不是 gc(对于垃圾收集类型)是为了便于更好地暗示这个类型的本质。 2.1.1指定一个类为抽象类型 在原版语言定义中,要害字 __abstract放在类型要害字之前(__gc之前或者之后)以指明该类尚未完成,而且此类的对象不能在程序中创建:   public __gc __abstract class Shape {};    public __gc __abstract class Shape2D: public Shape {}; 在修订版语言设计中,abstract 与上下文相关的要害字被限定在类名之后,类体、基类派生列表或者分号之前。   public ref class Shape abstract {};    public ref class Shape2D abstract : public Shape{}; 当然,语义没有变化。 2.1.2指定一个类为密封类型 在原版语言定义中,要害字 __sealed放在 class 要害字之前(__gc之前或者之后)以指明类的对象不能从以下类继续:   public __gc __sealed class String {};
在 V2语言设计中,与上下文相关的抽象要害字限定在类名之后,类体、基类派生列表或者分号之前(您可以声明一个继续类并密封它。举例来说,String类隐式派生自Object)。密封一个类的好处是答应静态(即在编译时)解析这个密封引用类对象的所有的虚函数调用。这是因为密封指示符保证了 String跟踪句柄不能指向一个可能重载被调用的虚方法实例的派生类。   public ref class String sealed {}; 也可以将一个类既声明为抽象类也声明为密封类。这是一种被称为静态类的非凡情况。这在CLI文档中描述如下: 同时为抽象和密封的类型只能有静态成员,并且以一些语言中调用命名空间一样的方式服务。 例如,以下是一个使用 V1语法的抽象密封类的声明   public __gc __sealed __abstract class State  { public:    static State();    static bool inParamList(); private:    static bool ms_inParam; }; 而以下是在修订版语言设计中的声明:    public ref class State abstract sealed { public:    static State();    static bool inParamList(); private:    static bool ms_inParam; }; 2.1.3 CLI继续: 指定基类 在 CLI对象模型中,只支持公有方式的单继续。但是,在原始语言定义中仍然保留了ISO-C++对基类的默认解释,而无需访问要害字指定私有派生。这意味着每一个 CLI继续声明必须用一个 public要害字来代替默认的解释。很多用户认为编译器似乎过于严谨。// V1:错误:默认为私有派生 __gc class My : File{}; 在修订版语言定义中,CLI继续定义缺少访问要害字时,默认是以公有的方式派生。这样,公有访问要害字就不再必要,而是可选的。虽然这个改变不需要对 V1的代码做任何的修改,出于完整性考虑我仍将这个变化列出。// V2:正确:默认是公有性派生 ref class My : File{};

简介   C++/CLI代表 ISO-C++标准语言的一个动态编程泛型扩展 (dynamic programming paradigm extension)。在原版语言设计 (V1) 中有许多显著的弱点,我们觉得在修订版语言设计 (V2) 中已经修正了这些弱点。本文列举了 V1 版本语言的功能和它们在 V2 版本中的对应功能(假如存在);并指出了其对应功能不存在的构造。对于有爱好的读者,可以查看附录中提供新语言设计的扩展原理。另外,一个源代码级别的转换工具 (mscfront) 正在开发中,而且可能在 C++/CLI的发布版中提供给希望将 V1 代码自动移植到新语言设计的人。   本文分为五个章节加一个附录。第一节讨论语言要害字的主要问题,非凡是双下划线的移除以及与上下文相关和由空格分隔的要害字。第二节着眼于托管类型的变化 — 非凡是托管引用类型和数组。还可以在这里找到有关确定性终结语义 (deterministic finalization) 的具体讨论。关于类成员的变化,例如属性、索引属性和操作符,是第三节的重点。第四节着眼于 CLI 枚举、内部和钉住指针的语法变化。它也讨论了许多可观的语义变化,例如隐式装箱的引入、CLI枚举的变化,和对值类中默认构造函数的支持的移除。第五节有点像大杂烩 — 乱七八糟的杂项。讨论了类型转换符号、字符串字符的行为和参数数组。   1. 语言要害字   原版到修订版语言设计的一个重要转换是在所有要害字中去掉双下划线。举例来说,一个属性现在被声明为 property而不是 __property。在原版语言设计中使用双下划线前缀的两个主要原因是:   1. 这是提供符合 ISO-C++标准的本地扩展的一致性方法。原版语言设计的一个主要目标就是不引入与标准语言的不兼容性,例如新的要害字和标记。这个原因很大程度上也推动了对声明托管引用类型的对象的指针语法的选择。 2. 双下划线的使用,除了兼容性方面的原因之外,也是一个不会对有旧代码基础的用户造成影响的合理保证。这是原版语言设计的第二主要目标。   这样的话,为什么我们移除双下划线(并且引入了一些新的标记)?不是的,这并不代表我们不再考虑和标准保持一致!   我们继续致力于和标准一致。尽管如此,我们意识到对 CLI动态对象模型的支持表现出了一种全新的强大的编程范型。我们在原版语言设计上的经验以及设计与发展 C++ 语言本身的经验使我们确信,对这个新范型的支持需要它自己的高级要害字和标记。我们想提供一个该新范型的一流表达方式,整合它并且支持标准语言。我们希望您会感受到修订版语言设计提供了对这两种截然不同的对象模型的一流的编程体验。   类似的,我们很关心最小化这些新的要害字的对现有代码可能造成的冲击。这是用与上下文相关和由空格分隔的要害字来解决的。在我们着眼于实际语言语法的修订之前,让我们试试搞清楚这两个非凡要害字的特点。   一个与上下文相关的要害字在特定的程序上下文中有非凡的含义。例如,在通常的程序中,sealed 是一个普通标识符。但是,在一个托管引用类类型的声明部分,它就是类声明上下文中的一个要害字。这使得在语言中引入一个新的要害字的潜在影响降到最低程度,我们认为,这对已经拥有代码基的用户非常重要。同时,它答应新功能的使用者获得一流的新增语言功能的体验 — 我们认为在原版语言设计中缺少这些因素。我们将在 2.1.2节中看到 sealed用法的示例。   一个由空格分隔的要害字是与上下文相关要害字的特例。它在字面上将一个与上下文相关的修饰符和一个现存的要害字配对,用空格分隔。这个配对作为一个单独的单位,例如 value class(示例参见 1.1 节),而不是两个单独的要害字。基于现实的因素,这意味着一个重新定义 value 的宏,如下所示:      #ifndef __cplusplus_cli    #define value 不会在一个类声明中去掉 value。假如确实要这么做的话,必须重新定义单元对,编写如下代码:      #ifndef __cplusplus_cli 考虑到现实的因素,这是十分必要的。否则,现存的 #define可能转换由空格分隔的要害字的与上下文相关的要害字部分。  2.托管类型
声明托管类型和创建以及使用这些类型的对象的语法已经大加修改,以提高 ISO-C++类型系统内的集成性。这些更改在后面的小节中详述。委托的讨论延后到 2.3节以用类中的事件成员表述它们 — 这是第 2 节的主题。(有关更加具体的跟踪引用语法介绍的内幕和设计上的主要转变的讨论,请参见附录A:推动修订版语言设计。)

2.1 声明一个托管类类型

在原版语言定义中,一个引用类类型以 __gc要害字开头。在修订版语言中,__gc要害字被两个由空格分隔的要害字 ref class或者 ref struct之一替代。struct或者 class的选择只是指明在类型体中开头未标记部分声明的其成员的公共(对于 struct)或者私有(对于 class)默认访问级别。 类似地,在原版语言定义中,一个 value 类类型以 __value 要害字开头。在修订版语言中,__value 要害字被两个由空格分隔的要害字 value class或者 value struct之一代替。 在原版语言设计中,一个接口类型是用要害字 __interface指明的。在修订版语言中,它被 interface class替代。 例如,下列类声明对   // 原版语法     public __gc class Block { ... };   // 引用类    public __value class Vector { ... };   // 值类    public __interface IMyFile { ... };   // 接口类 在修订版语言设计下等价的声明如下:    // 修订版语法     public ref class Block { ... };    public value class Vector { ... };    public interface class IMyFile { ... }; 选择 ref(对于引用类型)而不是 gc(对于垃圾收集类型)是为了便于更好地暗示这个类型的本质。 2.1.1指定一个类为抽象类型 在原版语言定义中,要害字 __abstract放在类型要害字之前(__gc之前或者之后)以指明该类尚未完成,而且此类的对象不能在程序中创建:   public __gc __abstract class Shape {};    public __gc __abstract class Shape2D: public Shape {}; 在修订版语言设计中,abstract 与上下文相关的要害字被限定在类名之后,类体、基类派生列表或者分号之前。   public ref class Shape abstract {};    public ref class Shape2D abstract : public Shape{}; 当然,语义没有变化。 2.1.2指定一个类为密封类型 在原版语言定义中,要害字 __sealed放在 class 要害字之前(__gc之前或者之后)以指明类的对象不能从以下类继续:   public __gc __sealed class String {};
在 V2语言设计中,与上下文相关的抽象要害字限定在类名之后,类体、基类派生列表或者分号之前(您可以声明一个继续类并密封它。举例来说,String类隐式派生自Object)。密封一个类的好处是答应静态(即在编译时)解析这个密封引用类对象的所有的虚函数调用。这是因为密封指示符保证了 String跟踪句柄不能指向一个可能重载被调用的虚方法实例的派生类。   public ref class String sealed {}; 也可以将一个类既声明为抽象类也声明为密封类。这是一种被称为静态类的非凡情况。这在CLI文档中描述如下: 同时为抽象和密封的类型只能有静态成员,并且以一些语言中调用命名空间一样的方式服务。 例如,以下是一个使用 V1语法的抽象密封类的声明   public __gc __sealed __abstract class State  { public:    static State();    static bool inParamList(); private:    static bool ms_inParam; }; 而以下是在修订版语言设计中的声明:    public ref class State abstract sealed { public:    static State();    static bool inParamList(); private:    static bool ms_inParam; }; 2.1.3 CLI继续: 指定基类 在 CLI对象模型中,只支持公有方式的单继续。但是,在原始语言定义中仍然保留了ISO-C++对基类的默认解释,而无需访问要害字指定私有派生。这意味着每一个 CLI继续声明必须用一个 public要害字来代替默认的解释。很多用户认为编译器似乎过于严谨。// V1:错误:默认为私有派生 __gc class My : File{}; 在修订版语言定义中,CLI继续定义缺少访问要害字时,默认是以公有的方式派生。这样,公有访问要害字就不再必要,而是可选的。虽然这个改变不需要对 V1的代码做任何的修改,出于完整性考虑我仍将这个变化列出。// V2:正确:默认是公有性派生 ref class My : File{};

简介   C++/CLI代表 ISO-C++标准语言的一个动态编程泛型扩展 (dynamic programming paradigm extension)。在原版语言设计 (V1) 中有许多显著的弱点,我们觉得在修订版语言设计 (V2) 中已经修正了这些弱点。本文列举了 V1 版本语言的功能和它们在 V2 版本中的对应功能(假如存在);并指出了其对应功能不存在的构造。对于有爱好的读者,可以查看附录中提供新语言设计的扩展原理。另外,一个源代码级别的转换工具 (mscfront) 正在开发中,而且可能在 C++/CLI的发布版中提供给希望将 V1 代码自动移植到新语言设计的人。   本文分为五个章节加一个附录。第一节讨论语言要害字的主要问题,非凡是双下划线的移除以及与上下文相关和由空格分隔的要害字。第二节着眼于托管类型的变化 — 非凡是托管引用类型和数组。还可以在这里找到有关确定性终结语义 (deterministic finalization) 的具体讨论。关于类成员的变化,例如属性、索引属性和操作符,是第三节的重点。第四节着眼于 CLI 枚举、内部和钉住指针的语法变化。它也讨论了许多可观的语义变化,例如隐式装箱的引入、CLI枚举的变化,和对值类中默认构造函数的支持的移除。第五节有点像大杂烩 — 乱七八糟的杂项。讨论了类型转换符号、字符串字符的行为和参数数组。   1. 语言要害字   原版到修订版语言设计的一个重要转换是在所有要害字中去掉双下划线。举例来说,一个属性现在被声明为 property而不是 __property。在原版语言设计中使用双下划线前缀的两个主要原因是:   1. 这是提供符合 ISO-C++标准的本地扩展的一致性方法。原版语言设计的一个主要目标就是不引入与标准语言的不兼容性,例如新的要害字和标记。这个原因很大程度上也推动了对声明托管引用类型的对象的指针语法的选择。 2. 双下划线的使用,除了兼容性方面的原因之外,也是一个不会对有旧代码基础的用户造成影响的合理保证。这是原版语言设计的第二主要目标。   这样的话,为什么我们移除双下划线(并且引入了一些新的标记)?不是的,这并不代表我们不再考虑和标准保持一致!   我们继续致力于和标准一致。尽管如此,我们意识到对 CLI动态对象模型的支持表现出了一种全新的强大的编程范型。我们在原版语言设计上的经验以及设计与发展 C++ 语言本身的经验使我们确信,对这个新范型的支持需要它自己的高级要害字和标记。我们想提供一个该新范型的一流表达方式,整合它并且支持标准语言。我们希望您会感受到修订版语言设计提供了对这两种截然不同的对象模型的一流的编程体验。   类似的,我们很关心最小化这些新的要害字的对现有代码可能造成的冲击。这是用与上下文相关和由空格分隔的要害字来解决的。在我们着眼于实际语言语法的修订之前,让我们试试搞清楚这两个非凡要害字的特点。   一个与上下文相关的要害字在特定的程序上下文中有非凡的含义。例如,在通常的程序中,sealed 是一个普通标识符。但是,在一个托管引用类类型的声明部分,它就是类声明上下文中的一个要害字。这使得在语言中引入一个新的要害字的潜在影响降到最低程度,我们认为,这对已经拥有代码基的用户非常重要。同时,它答应新功能的使用者获得一流的新增语言功能的体验 — 我们认为在原版语言设计中缺少这些因素。我们将在 2.1.2节中看到 sealed用法的示例。   一个由空格分隔的要害字是与上下文相关要害字的特例。它在字面上将一个与上下文相关的修饰符和一个现存的要害字配对,用空格分隔。这个配对作为一个单独的单位,例如 value class(示例参见 1.1 节),而不是两个单独的要害字。基于现实的因素,这意味着一个重新定义 value 的宏,如下所示:      #ifndef __cplusplus_cli    #define value 不会在一个类声明中去掉 value。假如确实要这么做的话,必须重新定义单元对,编写如下代码:      #ifndef __cplusplus_cli 考虑到现实的因素,这是十分必要的。否则,现存的 #define可能转换由空格分隔的要害字的与上下文相关的要害字部分。  2.托管类型
声明托管类型和创建以及使用这些类型的对象的语法已经大加修改,以提高 ISO-C++类型系统内的集成性。这些更改在后面的小节中详述。委托的讨论延后到 2.3节以用类中的事件成员表述它们 — 这是第 2 节的主题。(有关更加具体的跟踪引用语法介绍的内幕和设计上的主要转变的讨论,请参见附录A:推动修订版语言设计。)

2.1 声明一个托管类类型

在原版语言定义中,一个引用类类型以 __gc要害字开头。在修订版语言中,__gc要害字被两个由空格分隔的要害字 ref class或者 ref struct之一替代。struct或者 class的选择只是指明在类型体中开头未标记部分声明的其成员的公共(对于 struct)或者私有(对于 class)默认访问级别。 类似地,在原版语言定义中,一个 value 类类型以 __value 要害字开头。在修订版语言中,__value 要害字被两个由空格分隔的要害字 value class或者 value struct之一代替。 在原版语言设计中,一个接口类型是用要害字 __interface指明的。在修订版语言中,它被 interface class替代。 例如,下列类声明对   // 原版语法     public __gc class Block { ... };   // 引用类    public __value class Vector { ... };   // 值类    public __interface IMyFile { ... };   // 接口类 在修订版语言设计下等价的声明如下:    // 修订版语法     public ref class Block { ... };    public value class Vector { ... };    public interface class IMyFile { ... }; 选择 ref(对于引用类型)而不是 gc(对于垃圾收集类型)是为了便于更好地暗示这个类型的本质。 2.1.1指定一个类为抽象类型 在原版语言定义中,要害字 __abstract放在类型要害字之前(__gc之前或者之后)以指明该类尚未完成,而且此类的对象不能在程序中创建:   public __gc __abstract class Shape {};    public __gc __abstract class Shape2D: public Shape {}; 在修订版语言设计中,abstract 与上下文相关的要害字被限定在类名之后,类体、基类派生列表或者分号之前。   public ref class Shape abstract {};    public ref class Shape2D abstract : public Shape{}; 当然,语义没有变化。 2.1.2指定一个类为密封类型 在原版语言定义中,要害字 __sealed放在 class 要害字之前(__gc之前或者之后)以指明类的对象不能从以下类继续:   public __gc __sealed class String {};
在 V2语言设计中,与上下文相关的抽象要害字限定在类名之后,类体、基类派生列表或者分号之前(您可以声明一个继续类并密封它。举例来说,String类隐式派生自Object)。密封一个类的好处是答应静态(即在编译时)解析这个密封引用类对象的所有的虚函数调用。这是因为密封指示符保证了 String跟踪句柄不能指向一个可能重载被调用的虚方法实例的派生类。   public ref class String sealed {}; 也可以将一个类既声明为抽象类也声明为密封类。这是一种被称为静态类的非凡情况。这在CLI文档中描述如下: 同时为抽象和密封的类型只能有静态成员,并且以一些语言中调用命名空间一样的方式服务。 例如,以下是一个使用 V1语法的抽象密封类的声明   public __gc __sealed __abstract class State  { public:    static State();    static bool inParamList(); private:    static bool ms_inParam; }; 而以下是在修订版语言设计中的声明:    public ref class State abstract sealed { public:    static State();    static bool inParamList(); private:    static bool ms_inParam; }; 2.1.3 CLI继续: 指定基类 在 CLI对象模型中,只支持公有方式的单继续。但是,在原始语言定义中仍然保留了ISO-C++对基类的默认解释,而无需访问要害字指定私有派生。这意味着每一个 CLI继续声明必须用一个 public要害字来代替默认的解释。很多用户认为编译器似乎过于严谨。// V1:错误:默认为私有派生 __gc class My : File{}; 在修订版语言定义中,CLI继续定义缺少访问要害字时,默认是以公有的方式派生。这样,公有访问要害字就不再必要,而是可选的。虽然这个改变不需要对 V1的代码做任何的修改,出于完整性考虑我仍将这个变化列出。// V2:正确:默认是公有性派生 ref class My : File{};

简介   C++/CLI代表 ISO-C++标准语言的一个动态编程泛型扩展 (dynamic programming paradigm extension)。在原版语言设计 (V1) 中有许多显著的弱点,我们觉得在修订版语言设计 (V2) 中已经修正了这些弱点。本文列举了 V1 版本语言的功能和它们在 V2 版本中的对应功能(假如存在);并指出了其对应功能不存在的构造。对于有爱好的读者,可以查看附录中提供新语言设计的扩展原理。另外,一个源代码级别的转换工具 (mscfront) 正在开发中,而且可能在 C++/CLI的发布版中提供给希望将 V1 代码自动移植到新语言设计的人。   本文分为五个章节加一个附录。第一节讨论语言要害字的主要问题,非凡是双下划线的移除以及与上下文相关和由空格分隔的要害字。第二节着眼于托管类型的变化 — 非凡是托管引用类型和数组。还可以在这里找到有关确定性终结语义 (deterministic finalization) 的具体讨论。关于类成员的变化,例如属性、索引属性和操作符,是第三节的重点。第四节着眼于 CLI 枚举、内部和钉住指针的语法变化。它也讨论了许多可观的语义变化,例如隐式装箱的引入、CLI枚举的变化,和对值类中默认构造函数的支持的移除。第五节有点像大杂烩 — 乱七八糟的杂项。讨论了类型转换符号、字符串字符的行为和参数数组。   1. 语言要害字   原版到修订版语言设计的一个重要转换是在所有要害字中去掉双下划线。举例来说,一个属性现在被声明为 property而不是 __property。在原版语言设计中使用双下划线前缀的两个主要原因是:   1. 这是提供符合 ISO-C++标准的本地扩展的一致性方法。原版语言设计的一个主要目标就是不引入与标准语言的不兼容性,例如新的要害字和标记。这个原因很大程度上也推动了对声明托管引用类型的对象的指针语法的选择。 2. 双下划线的使用,除了兼容性方面的原因之外,也是一个不会对有旧代码基础的用户造成影响的合理保证。这是原版语言设计的第二主要目标。   这样的话,为什么我们移除双下划线(并且引入了一些新的标记)?不是的,这并不代表我们不再考虑和标准保持一致!   我们继续致力于和标准一致。尽管如此,我们意识到对 CLI动态对象模型的支持表现出了一种全新的强大的编程范型。我们在原版语言设计上的经验以及设计与发展 C++ 语言本身的经验使我们确信,对这个新范型的支持需要它自己的高级要害字和标记。我们想提供一个该新范型的一流表达方式,整合它并且支持标准语言。我们希望您会感受到修订版语言设计提供了对这两种截然不同的对象模型的一流的编程体验。   类似的,我们很关心最小化这些新的要害字的对现有代码可能造成的冲击。这是用与上下文相关和由空格分隔的要害字来解决的。在我们着眼于实际语言语法的修订之前,让我们试试搞清楚这两个非凡要害字的特点。   一个与上下文相关的要害字在特定的程序上下文中有非凡的含义。例如,在通常的程序中,sealed 是一个普通标识符。但是,在一个托管引用类类型的声明部分,它就是类声明上下文中的一个要害字。这使得在语言中引入一个新的要害字的潜在影响降到最低程度,我们认为,这对已经拥有代码基的用户非常重要。同时,它答应新功能的使用者获得一流的新增语言功能的体验 — 我们认为在原版语言设计中缺少这些因素。我们将在 2.1.2节中看到 sealed用法的示例。   一个由空格分隔的要害字是与上下文相关要害字的特例。它在字面上将一个与上下文相关的修饰符和一个现存的要害字配对,用空格分隔。这个配对作为一个单独的单位,例如 value class(示例参见 1.1 节),而不是两个单独的要害字。基于现实的因素,这意味着一个重新定义 value 的宏,如下所示:      #ifndef __cplusplus_cli    #define value 不会在一个类声明中去掉 value。假如确实要这么做的话,必须重新定义单元对,编写如下代码:      #ifndef __cplusplus_cli 考虑到现实的因素,这是十分必要的。否则,现存的 #define可能转换由空格分隔的要害字的与上下文相关的要害字部分。  2.托管类型
声明托管类型和创建以及使用这些类型的对象的语法已经大加修改,以提高 ISO-C++类型系统内的集成性。这些更改在后面的小节中详述。委托的讨论延后到 2.3节以用类中的事件成员表述它们 — 这是第 2 节的主题。(有关更加具体的跟踪引用语法介绍的内幕和设计上的主要转变的讨论,请参见附录A:推动修订版语言设计。)

2.1 声明一个托管类类型

在原版语言定义中,一个引用类类型以 __gc要害字开头。在修订版语言中,__gc要害字被两个由空格分隔的要害字 ref class或者 ref struct之一替代。struct或者 class的选择只是指明在类型体中开头未标记部分声明的其成员的公共(对于 struct)或者私有(对于 class)默认访问级别。 类似地,在原版语言定义中,一个 value 类类型以 __value 要害字开头。在修订版语言中,__value 要害字被两个由空格分隔的要害字 value class或者 value struct之一代替。 在原版语言设计中,一个接口类型是用要害字 __interface指明的。在修订版语言中,它被 interface class替代。 例如,下列类声明对   // 原版语法     public __gc class Block { ... };   // 引用类    public __value class Vector { ... };   // 值类    public __interface IMyFile { ... };   // 接口类 在修订版语言设计下等价的声明如下:    // 修订版语法     public ref class Block { ... };    public value class Vector { ... };    public interface class IMyFile { ... }; 选择 ref(对于引用类型)而不是 gc(对于垃圾收集类型)是为了便于更好地暗示这个类型的本质。 2.1.1指定一个类为抽象类型 在原版语言定义中,要害字 __abstract放在类型要害字之前(__gc之前或者之后)以指明该类尚未完成,而且此类的对象不能在程序中创建:   public __gc __abstract class Shape {};    public __gc __abstract class Shape2D: public Shape {}; 在修订版语言设计中,abstract 与上下文相关的要害字被限定在类名之后,类体、基类派生列表或者分号之前。   public ref class Shape abstract {};    public ref class Shape2D abstract : public Shape{}; 当然,语义没有变化。 2.1.2指定一个类为密封类型 在原版语言定义中,要害字 __sealed放在 class 要害字之前(__gc之前或者之后)以指明类的对象不能从以下类继续:   public __gc __sealed class String {};
在 V2语言设计中,与上下文相关的抽象要害字限定在类名之后,类体、基类派生列表或者分号之前(您可以声明一个继续类并密封它。举例来说,String类隐式派生自Object)。密封一个类的好处是答应静态(即在编译时)解析这个密封引用类对象的所有的虚函数调用。这是因为密封指示符保证了 String跟踪句柄不能指向一个可能重载被调用的虚方法实例的派生类。   public ref class String sealed {}; 也可以将一个类既声明为抽象类也声明为密封类。这是一种被称为静态类的非凡情况。这在CLI文档中描述如下: 同时为抽象和密封的类型只能有静态成员,并且以一些语言中调用命名空间一样的方式服务。 例如,以下是一个使用 V1语法的抽象密封类的声明   public __gc __sealed __abstract class State  { public:    static State();    static bool inParamList(); private:    static bool ms_inParam; }; 而以下是在修订版语言设计中的声明:    public ref class State abstract sealed { public:    static State();    static bool inParamList(); private:    static bool ms_inParam; }; 2.1.3 CLI继续: 指定基类 在 CLI对象模型中,只支持公有方式的单继续。但是,在原始语言定义中仍然保留了ISO-C++对基类的默认解释,而无需访问要害字指定私有派生。这意味着每一个 CLI继续声明必须用一个 public要害字来代替默认的解释。很多用户认为编译器似乎过于严谨。// V1:错误:默认为私有派生 __gc class My : File{}; 在修订版语言定义中,CLI继续定义缺少访问要害字时,默认是以公有的方式派生。这样,公有访问要害字就不再必要,而是可选的。虽然这个改变不需要对 V1的代码做任何的修改,出于完整性考虑我仍将这个变化列出。// V2:正确:默认是公有性派生 ref class My : File{};

简介   C++/CLI代表 ISO-C++标准语言的一个动态编程泛型扩展 (dynamic programming paradigm extension)。在原版语言设计 (V1) 中有许多显著的弱点,我们觉得在修订版语言设计 (V2) 中已经修正了这些弱点。本文列举了 V1 版本语言的功能和它们在 V2 版本中的对应功能(假如存在);并指出了其对应功能不存在的构造。对于有爱好的读者,可以查看附录中提供新语言设计的扩展原理。另外,一个源代码级别的转换工具 (mscfront) 正在开发中,而且可能在 C++/CLI的发布版中提供给希望将 V1 代码自动移植到新语言设计的人。   本文分为五个章节加一个附录。第一节讨论语言要害字的主要问题,非凡是双下划线的移除以及与上下文相关和由空格分隔的要害字。第二节着眼于托管类型的变化 — 非凡是托管引用类型和数组。还可以在这里找到有关确定性终结语义 (deterministic finalization) 的具体讨论。关于类成员的变化,例如属性、索引属性和操作符,是第三节的重点。第四节着眼于 CLI 枚举、内部和钉住指针的语法变化。它也讨论了许多可观的语义变化,例如隐式装箱的引入、CLI枚举的变化,和对值类中默认构造函数的支持的移除。第五节有点像大杂烩 — 乱七八糟的杂项。讨论了类型转换符号、字符串字符的行为和参数数组。   1. 语言要害字   原版到修订版语言设计的一个重要转换是在所有要害字中去掉双下划线。举例来说,一个属性现在被声明为 property而不是 __property。在原版语言设计中使用双下划线前缀的两个主要原因是:   1. 这是提供符合 ISO-C++标准的本地扩展的一致性方法。原版语言设计的一个主要目标就是不引入与标准语言的不兼容性,例如新的要害字和标记。这个原因很大程度上也推动了对声明托管引用类型的对象的指针语法的选择。 2. 双下划线的使用,除了兼容性方面的原因之外,也是一个不会对有旧代码基础的用户造成影响的合理保证。这是原版语言设计的第二主要目标。   这样的话,为什么我们移除双下划线(并且引入了一些新的标记)?不是的,这并不代表我们不再考虑和标准保持一致!   我们继续致力于和标准一致。尽管如此,我们意识到对 CLI动态对象模型的支持表现出了一种全新的强大的编程范型。我们在原版语言设计上的经验以及设计与发展 C++ 语言本身的经验使我们确信,对这个新范型的支持需要它自己的高级要害字和标记。我们想提供一个该新范型的一流表达方式,整合它并且支持标准语言。我们希望您会感受到修订版语言设计提供了对这两种截然不同的对象模型的一流的编程体验。   类似的,我们很关心最小化这些新的要害字的对现有代码可能造成的冲击。这是用与上下文相关和由空格分隔的要害字来解决的。在我们着眼于实际语言语法的修订之前,让我们试试搞清楚这两个非凡要害字的特点。   一个与上下文相关的要害字在特定的程序上下文中有非凡的含义。例如,在通常的程序中,sealed 是一个普通标识符。但是,在一个托管引用类类型的声明部分,它就是类声明上下文中的一个要害字。这使得在语言中引入一个新的要害字的潜在影响降到最低程度,我们认为,这对已经拥有代码基的用户非常重要。同时,它答应新功能的使用者获得一流的新增语言功能的体验 — 我们认为在原版语言设计中缺少这些因素。我们将在 2.1.2节中看到 sealed用法的示例。   一个由空格分隔的要害字是与上下文相关要害字的特例。它在字面上将一个与上下文相关的修饰符和一个现存的要害字配对,用空格分隔。这个配对作为一个单独的单位,例如 value class(示例参见 1.1 节),而不是两个单独的要害字。基于现实的因素,这意味着一个重新定义 value 的宏,如下所示:      #ifndef __cplusplus_cli    #define value 不会在一个类声明中去掉 value。假如确实要这么做的话,必须重新定义单元对,编写如下代码:      #ifndef __cplusplus_cli 考虑到现实的因素,这是十分必要的。否则,现存的 #define可能转换由空格分隔的要害字的与上下文相关的要害字部分。  2.托管类型
声明托管类型和创建以及使用这些类型的对象的语法已经大加修改,以提高 ISO-C++类型系统内的集成性。这些更改在后面的小节中详述。委托的讨论延后到 2.3节以用类中的事件成员表述它们 — 这是第 2 节的主题。(有关更加具体的跟踪引用语法介绍的内幕和设计上的主要转变的讨论,请参见附录A:推动修订版语言设计。)

2.1 声明一个托管类类型

在原版语言定义中,一个引用类类型以 __gc要害字开头。在修订版语言中,__gc要害字被两个由空格分隔的要害字 ref class或者 ref struct之一替代。struct或者 class的选择只是指明在类型体中开头未标记部分声明的其成员的公共(对于 struct)或者私有(对于 class)默认访问级别。 类似地,在原版语言定义中,一个 value 类类型以 __value 要害字开头。在修订版语言中,__value 要害字被两个由空格分隔的要害字 value class或者 value struct之一代替。 在原版语言设计中,一个接口类型是用要害字 __interface指明的。在修订版语言中,它被 interface class替代。 例如,下列类声明对   // 原版语法     public __gc class Block { ... };   // 引用类    public __value class Vector { ... };   // 值类    public __interface IMyFile { ... };   // 接口类 在修订版语言设计下等价的声明如下:    // 修订版语法     public ref class Block { ... };    public value class Vector { ... };    public interface class IMyFile { ... }; 选择 ref(对于引用类型)而不是 gc(对于垃圾收集类型)是为了便于更好地暗示这个类型的本质。 2.1.1指定一个类为抽象类型 在原版语言定义中,要害字 __abstract放在类型要害字之前(__gc之前或者之后)以指明该类尚未完成,而且此类的对象不能在程序中创建:   public __gc __abstract class Shape {};    public __gc __abstract class Shape2D: public Shape {}; 在修订版语言设计中,abstract 与上下文相关的要害字被限定在类名之后,类体、基类派生列表或者分号之前。   public ref class Shape abstract {};    public ref class Shape2D abstract : public Shape{}; 当然,语义没有变化。 2.1.2指定一个类为密封类型 在原版语言定义中,要害字 __sealed放在 class 要害字之前(__gc之前或者之后)以指明类的对象不能从以下类继续:   public __gc __sealed class String {};
在 V2语言设计中,与上下文相关的抽象要害字限定在类名之后,类体、基类派生列表或者分号之前(您可以声明一个继续类并密封它。举例来说,String类隐式派生自Object)。密封一个类的好处是答应静态(即在编译时)解析这个密封引用类对象的所有的虚函数调用。这是因为密封指示符保证了 String跟踪句柄不能指向一个可能重载被调用的虚方法实例的派生类。   public ref class String sealed {}; 也可以将一个类既声明为抽象类也声明为密封类。这是一种被称为静态类的非凡情况。这在CLI文档中描述如下: 同时为抽象和密封的类型只能有静态成员,并且以一些语言中调用命名空间一样的方式服务。 例如,以下是一个使用 V1语法的抽象密封类的声明   public __gc __sealed __abstract class State  { public:    static State();    static bool inParamList(); private:    static bool ms_inParam; }; 而以下是在修订版语言设计中的声明:    public ref class State abstract sealed { public:    static State();    static bool inParamList(); private:    static bool ms_inParam; }; 2.1.3 CLI继续: 指定基类 在 CLI对象模型中,只支持公有方式的单继续。但是,在原始语言定义中仍然保留了ISO-C++对基类的默认解释,而无需访问要害字指定私有派生。这意味着每一个 CLI继续声明必须用一个 public要害字来代替默认的解释。很多用户认为编译器似乎过于严谨。// V1:错误:默认为私有派生 __gc class My : File{}; 在修订版语言定义中,CLI继续定义缺少访问要害字时,默认是以公有的方式派生。这样,公有访问要害字就不再必要,而是可选的。虽然这个改变不需要对 V1的代码做任何的修改,出于完整性考虑我仍将这个变化列出。// V2:正确:默认是公有性派生 ref class My : File{};

简介   C++/CLI代表 ISO-C++标准语言的一个动态编程泛型扩展 (dynamic programming paradigm extension)。在原版语言设计 (V1) 中有许多显著的弱点,我们觉得在修订版语言设计 (V2) 中已经修正了这些弱点。本文列举了 V1 版本语言的功能和它们在 V2 版本中的对应功能(假如存在);并指出了其对应功能不存在的构造。对于有爱好的读者,可以查看附录中提供新语言设计的扩展原理。另外,一个源代码级别的转换工具 (mscfront) 正在开发中,而且可能在 C++/CLI的发布版中提供给希望将 V1 代码自动移植到新语言设计的人。   本文分为五个章节加一个附录。第一节讨论语言要害字的主要问题,非凡是双下划线的移除以及与上下文相关和由空格分隔的要害字。第二节着眼于托管类型的变化 — 非凡是托管引用类型和数组。还可以在这里找到有关确定性终结语义 (deterministic finalization) 的具体讨论。关于类成员的变化,例如属性、索引属性和操作符,是第三节的重点。第四节着眼于 CLI 枚举、内部和钉住指针的语法变化。它也讨论了许多可观的语义变化,例如隐式装箱的引入、CLI枚举的变化,和对值类中默认构造函数的支持的移除。第五节有点像大杂烩 — 乱七八糟的杂项。讨论了类型转换符号、字符串字符的行为和参数数组。   1. 语言要害字   原版到修订版语言设计的一个重要转换是在所有要害字中去掉双下划线。举例来说,一个属性现在被声明为 property而不是 __property。在原版语言设计中使用双下划线前缀的两个主要原因是:   1. 这是提供符合 ISO-C++标准的本地扩展的一致性方法。原版语言设计的一个主要目标就是不引入与标准语言的不兼容性,例如新的要害字和标记。这个原因很大程度上也推动了对声明托管引用类型的对象的指针语法的选择。 2. 双下划线的使用,除了兼容性方面的原因之外,也是一个不会对有旧代码基础的用户造成影响的合理保证。这是原版语言设计的第二主要目标。   这样的话,为什么我们移除双下划线(并且引入了一些新的标记)?不是的,这并不代表我们不再考虑和标准保持一致!   我们继续致力于和标准一致。尽管如此,我们意识到对 CLI动态对象模型的支持表现出了一种全新的强大的编程范型。我们在原版语言设计上的经验以及设计与发展 C++ 语言本身的经验使我们确信,对这个新范型的支持需要它自己的高级要害字和标记。我们想提供一个该新范型的一流表达方式,整合它并且支持标准语言。我们希望您会感受到修订版语言设计提供了对这两种截然不同的对象模型的一流的编程体验。   类似的,我们很关心最小化这些新的要害字的对现有代码可能造成的冲击。这是用与上下文相关和由空格分隔的要害字来解决的。在我们着眼于实际语言语法的修订之前,让我们试试搞清楚这两个非凡要害字的特点。   一个与上下文相关的要害字在特定的程序上下文中有非凡的含义。例如,在通常的程序中,sealed 是一个普通标识符。但是,在一个托管引用类类型的声明部分,它就是类声明上下文中的一个要害字。这使得在语言中引入一个新的要害字的潜在影响降到最低程度,我们认为,这对已经拥有代码基的用户非常重要。同时,它答应新功能的使用者获得一流的新增语言功能的体验 — 我们认为在原版语言设计中缺少这些因素。我们将在 2.1.2节中看到 sealed用法的示例。   一个由空格分隔的要害字是与上下文相关要害字的特例。它在字面上将一个与上下文相关的修饰符和一个现存的要害字配对,用空格分隔。这个配对作为一个单独的单位,例如 value class(示例参见 1.1 节),而不是两个单独的要害字。基于现实的因素,这意味着一个重新定义 value 的宏,如下所示:      #ifndef __cplusplus_cli    #define value 不会在一个类声明中去掉 value。假如确实要这么做的话,必须重新定义单元对,编写如下代码:      #ifndef __cplusplus_cli 考虑到现实的因素,这是十分必要的。否则,现存的 #define可能转换由空格分隔的要害字的与上下文相关的要害字部分。  2.托管类型
声明托管类型和创建以及使用这些类型的对象的语法已经大加修改,以提高 ISO-C++类型系统内的集成性。这些更改在后面的小节中详述。委托的讨论延后到 2.3节以用类中的事件成员表述它们 — 这是第 2 节的主题。(有关更加具体的跟踪引用语法介绍的内幕和设计上的主要转变的讨论,请参见附录A:推动修订版语言设计。)

2.1 声明一个托管类类型

在原版语言定义中,一个引用类类型以 __gc要害字开头。在修订版语言中,__gc要害字被两个由空格分隔的要害字 ref class或者 ref struct之一替代。struct或者 class的选择只是指明在类型体中开头未标记部分声明的其成员的公共(对于 struct)或者私有(对于 class)默认访问级别。 类似地,在原版语言定义中,一个 value 类类型以 __value 要害字开头。在修订版语言中,__value 要害字被两个由空格分隔的要害字 value class或者 value struct之一代替。 在原版语言设计中,一个接口类型是用要害字 __interface指明的。在修订版语言中,它被 interface class替代。 例如,下列类声明对   // 原版语法     public __gc class Block { ... };   // 引用类    public __value class Vector { ... };   // 值类    public __interface IMyFile { ... };   // 接口类 在修订版语言设计下等价的声明如下:    // 修订版语法     public ref class Block { ... };    public value class Vector { ... };    public interface class IMyFile { ... }; 选择 ref(对于引用类型)而不是 gc(对于垃圾收集类型)是为了便于更好地暗示这个类型的本质。 2.1.1指定一个类为抽象类型 在原版语言定义中,要害字 __abstract放在类型要害字之前(__gc之前或者之后)以指明该类尚未完成,而且此类的对象不能在程序中创建:   public __gc __abstract class Shape {};    public __gc __abstract class Shape2D: public Shape {}; 在修订版语言设计中,abstract 与上下文相关的要害字被限定在类名之后,类体、基类派生列表或者分号之前。   public ref class Shape abstract {};    public ref class Shape2D abstract : public Shape{}; 当然,语义没有变化。 2.1.2指定一个类为密封类型 在原版语言定义中,要害字 __sealed放在 class 要害字之前(__gc之前或者之后)以指明类的对象不能从以下类继续:   public __gc __sealed class String {};
在 V2语言设计中,与上下文相关的抽象要害字限定在类名之后,类体、基类派生列表或者分号之前(您可以声明一个继续类并密封它。举例来说,String类隐式派生自Object)。密封一个类的好处是答应静态(即在编译时)解析这个密封引用类对象的所有的虚函数调用。这是因为密封指示符保证了 String跟踪句柄不能指向一个可能重载被调用的虚方法实例的派生类。   public ref class String sealed {}; 也可以将一个类既声明为抽象类也声明为密封类。这是一种被称为静态类的非凡情况。这在CLI文档中描述如下: 同时为抽象和密封的类型只能有静态成员,并且以一些语言中调用命名空间一样的方式服务。 例如,以下是一个使用 V1语法的抽象密封类的声明   public __gc __sealed __abstract class State  { public:    static State();    static bool inParamList(); private:    static bool ms_inParam; }; 而以下是在修订版语言设计中的声明:    public ref class State abstract sealed { public:    static State();    static bool inParamList(); private:    static bool ms_inParam; }; 2.1.3 CLI继续: 指定基类 在 CLI对象模型中,只支持公有方式的单继续。但是,在原始语言定义中仍然保留了ISO-C++对基类的默认解释,而无需访问要害字指定私有派生。这意味着每一个 CLI继续声明必须用一个 public要害字来代替默认的解释。很多用户认为编译器似乎过于严谨。// V1:错误:默认为私有派生 __gc class My : File{}; 在修订版语言定义中,CLI继续定义缺少访问要害字时,默认是以公有的方式派生。这样,公有访问要害字就不再必要,而是可选的。虽然这个改变不需要对 V1的代码做任何的修改,出于完整性考虑我仍将这个变化列出。// V2:正确:默认是公有性派生 ref class My : File{};

简介   C++/CLI代表 ISO-C++标准语言的一个动态编程泛型扩展 (dynamic programming paradigm extension)。在原版语言设计 (V1) 中有许多显著的弱点,我们觉得在修订版语言设计 (V2) 中已经修正了这些弱点。本文列举了 V1 版本语言的功能和它们在 V2 版本中的对应功能(假如存在);并指出了其对应功能不存在的构造。对于有爱好的读者,可以查看附录中提供新语言设计的扩展原理。另外,一个源代码级别的转换工具 (mscfront) 正在开发中,而且可能在 C++/CLI的发布版中提供给希望将 V1 代码自动移植到新语言设计的人。   本文分为五个章节加一个附录。第一节讨论语言要害字的主要问题,非凡是双下划线的移除以及与上下文相关和由空格分隔的要害字。第二节着眼于托管类型的变化 — 非凡是托管引用类型和数组。还可以在这里找到有关确定性终结语义 (deterministic finalization) 的具体讨论。关于类成员的变化,例如属性、索引属性和操作符,是第三节的重点。第四节着眼于 CLI 枚举、内部和钉住指针的语法变化。它也讨论了许多可观的语义变化,例如隐式装箱的引入、CLI枚举的变化,和对值类中默认构造函数的支持的移除。第五节有点像大杂烩 — 乱七八糟的杂项。讨论了类型转换符号、字符串字符的行为和参数数组。   1. 语言要害字   原版到修订版语言设计的一个重要转换是在所有要害字中去掉双下划线。举例来说,一个属性现在被声明为 property而不是 __property。在原版语言设计中使用双下划线前缀的两个主要原因是:   1. 这是提供符合 ISO-C++标准的本地扩展的一致性方法。原版语言设计的一个主要目标就是不引入与标准语言的不兼容性,例如新的要害字和标记。这个原因很大程度上也推动了对声明托管引用类型的对象的指针语法的选择。 2. 双下划线的使用,除了兼容性方面的原因之外,也是一个不会对有旧代码基础的用户造成影响的合理保证。这是原版语言设计的第二主要目标。   这样的话,为什么我们移除双下划线(并且引入了一些新的标记)?不是的,这并不代表我们不再考虑和标准保持一致!   我们继续致力于和标准一致。尽管如此,我们意识到对 CLI动态对象模型的支持表现出了一种全新的强大的编程范型。我们在原版语言设计上的经验以及设计与发展 C++ 语言本身的经验使我们确信,对这个新范型的支持需要它自己的高级要害字和标记。我们想提供一个该新范型的一流表达方式,整合它并且支持标准语言。我们希望您会感受到修订版语言设计提供了对这两种截然不同的对象模型的一流的编程体验。   类似的,我们很关心最小化这些新的要害字的对现有代码可能造成的冲击。这是用与上下文相关和由空格分隔的要害字来解决的。在我们着眼于实际语言语法的修订之前,让我们试试搞清楚这两个非凡要害字的特点。   一个与上下文相关的要害字在特定的程序上下文中有非凡的含义。例如,在通常的程序中,sealed 是一个普通标识符。但是,在一个托管引用类类型的声明部分,它就是类声明上下文中的一个要害字。这使得在语言中引入一个新的要害字的潜在影响降到最低程度,我们认为,这对已经拥有代码基的用户非常重要。同时,它答应新功能的使用者获得一流的新增语言功能的体验 — 我们认为在原版语言设计中缺少这些因素。我们将在 2.1.2节中看到 sealed用法的示例。   一个由空格分隔的要害字是与上下文相关要害字的特例。它在字面上将一个与上下文相关的修饰符和一个现存的要害字配对,用空格分隔。这个配对作为一个单独的单位,例如 value class(示例参见 1.1 节),而不是两个单独的要害字。基于现实的因素,这意味着一个重新定义 value 的宏,如下所示:      #ifndef __cplusplus_cli    #define value 不会在一个类声明中去掉 value。假如确实要这么做的话,必须重新定义单元对,编写如下代码:      #ifndef __cplusplus_cli 考虑到现实的因素,这是十分必要的。否则,现存的 #define可能转换由空格分隔的要害字的与上下文相关的要害字部分。  2.托管类型
声明托管类型和创建以及使用这些类型的对象的语法已经大加修改,以提高 ISO-C++类型系统内的集成性。这些更改在后面的小节中详述。委托的讨论延后到 2.3节以用类中的事件成员表述它们 — 这是第 2 节的主题。(有关更加具体的跟踪引用语法介绍的内幕和设计上的主要转变的讨论,请参见附录A:推动修订版语言设计。)

2.1 声明一个托管类类型

在原版语言定义中,一个引用类类型以 __gc要害字开头。在修订版语言中,__gc要害字被两个由空格分隔的要害字 ref class或者 ref struct之一替代。struct或者 class的选择只是指明在类型体中开头未标记部分声明的其成员的公共(对于 struct)或者私有(对于 class)默认访问级别。 类似地,在原版语言定义中,一个 value 类类型以 __value 要害字开头。在修订版语言中,__value 要害字被两个由空格分隔的要害字 value class或者 value struct之一代替。 在原版语言设计中,一个接口类型是用要害字 __interface指明的。在修订版语言中,它被 interface class替代。 例如,下列类声明对   // 原版语法     public __gc class Block { ... };   // 引用类    public __value class Vector { ... };   // 值类    public __interface IMyFile { ... };   // 接口类 在修订版语言设计下等价的声明如下:    // 修订版语法     public ref class Block { ... };    public value class Vector { ... };    public interface class IMyFile { ... }; 选择 ref(对于引用类型)而不是 gc(对于垃圾收集类型)是为了便于更好地暗示这个类型的本质。 2.1.1指定一个类为抽象类型 在原版语言定义中,要害字 __abstract放在类型要害字之前(__gc之前或者之后)以指明该类尚未完成,而且此类的对象不能在程序中创建:   public __gc __abstract class Shape {};    public __gc __abstract class Shape2D: public Shape {}; 在修订版语言设计中,abstract 与上下文相关的要害字被限定在类名之后,类体、基类派生列表或者分号之前。   public ref class Shape abstract {};    public ref class Shape2D abstract : public Shape{}; 当然,语义没有变化。 2.1.2指定一个类为密封类型 在原版语言定义中,要害字 __sealed放在 class 要害字之前(__gc之前或者之后)以指明类的对象不能从以下类继续:   public __gc __sealed class String {};
在 V2语言设计中,与上下文相关的抽象要害字限定在类名之后,类体、基类派生列表或者分号之前(您可以声明一个继续类并密封它。举例来说,String类隐式派生自Object)。密封一个类的好处是答应静态(即在编译时)解析这个密封引用类对象的所有的虚函数调用。这是因为密封指示符保证了 String跟踪句柄不能指向一个可能重载被调用的虚方法实例的派生类。   public ref class String sealed {}; 也可以将一个类既声明为抽象类也声明为密封类。这是一种被称为静态类的非凡情况。这在CLI文档中描述如下: 同时为抽象和密封的类型只能有静态成员,并且以一些语言中调用命名空间一样的方式服务。 例如,以下是一个使用 V1语法的抽象密封类的声明   public __gc __sealed __abstract class State  { public:    static State();    static bool inParamList(); private:    static bool ms_inParam; }; 而以下是在修订版语言设计中的声明:    public ref class State abstract sealed { public:    static State();    static bool inParamList(); private:    static bool ms_inParam; }; 2.1.3 CLI继续: 指定基类 在 CLI对象模型中,只支持公有方式的单继续。但是,在原始语言定义中仍然保留了ISO-C++对基类的默认解释,而无需访问要害字指定私有派生。这意味着每一个 CLI继续声明必须用一个 public要害字来代替默认的解释。很多用户认为编译器似乎过于严谨。// V1:错误:默认为私有派生 __gc class My : File{}; 在修订版语言定义中,CLI继续定义缺少访问要害字时,默认是以公有的方式派生。这样,公有访问要害字就不再必要,而是可选的。虽然这个改变不需要对 V1的代码做任何的修改,出于完整性考虑我仍将这个变化列出。// V2:正确:默认是公有性派生 ref class My : File{};

简介   C++/CLI代表 ISO-C++标准语言的一个动态编程泛型扩展 (dynamic programming paradigm extension)。在原版语言设计 (V1) 中有许多显著的弱点,我们觉得在修订版语言设计 (V2) 中已经修正了这些弱点。本文列举了 V1 版本语言的功能和它们在 V2 版本中的对应功能(假如存在);并指出了其对应功能不存在的构造。对于有爱好的读者,可以查看附录中提供新语言设计的扩展原理。另外,一个源代码级别的转换工具 (mscfront) 正在开发中,而且可能在 C++/CLI的发布版中提供给希望将 V1 代码自动移植到新语言设计的人。   本文分为五个章节加一个附录。第一节讨论语言要害字的主要问题,非凡是双下划线的移除以及与上下文相关和由空格分隔的要害字。第二节着眼于托管类型的变化 — 非凡是托管引用类型和数组。还可以在这里找到有关确定性终结语义 (deterministic finalization) 的具体讨论。关于类成员的变化,例如属性、索引属性和操作符,是第三节的重点。第四节着眼于 CLI 枚举、内部和钉住指针的语法变化。它也讨论了许多可观的语义变化,例如隐式装箱的引入、CLI枚举的变化,和对值类中默认构造函数的支持的移除。第五节有点像大杂烩 — 乱七八糟的杂项。讨论了类型转换符号、字符串字符的行为和参数数组。   1. 语言要害字   原版到修订版语言设计的一个重要转换是在所有要害字中去掉双下划线。举例来说,一个属性现在被声明为 property而不是 __property。在原版语言设计中使用双下划线前缀的两个主要原因是:   1. 这是提供符合 ISO-C++标准的本地扩展的一致性方法。原版语言设计的一个主要目标就是不引入与标准语言的不兼容性,例如新的要害字和标记。这个原因很大程度上也推动了对声明托管引用类型的对象的指针语法的选择。 2. 双下划线的使用,除了兼容性方面的原因之外,也是一个不会对有旧代码基础的用户造成影响的合理保证。这是原版语言设计的第二主要目标。   这样的话,为什么我们移除双下划线(并且引入了一些新的标记)?不是的,这并不代表我们不再考虑和标准保持一致!   我们继续致力于和标准一致。尽管如此,我们意识到对 CLI动态对象模型的支持表现出了一种全新的强大的编程范型。我们在原版语言设计上的经验以及设计与发展 C++ 语言本身的经验使我们确信,对这个新范型的支持需要它自己的高级要害字和标记。我们想提供一个该新范型的一流表达方式,整合它并且支持标准语言。我们希望您会感受到修订版语言设计提供了对这两种截然不同的对象模型的一流的编程体验。   类似的,我们很关心最小化这些新的要害字的对现有代码可能造成的冲击。这是用与上下文相关和由空格分隔的要害字来解决的。在我们着眼于实际语言语法的修订之前,让我们试试搞清楚这两个非凡要害字的特点。   一个与上下文相关的要害字在特定的程序上下文中有非凡的含义。例如,在通常的程序中,sealed 是一个普通标识符。但是,在一个托管引用类类型的声明部分,它就是类声明上下文中的一个要害字。这使得在语言中引入一个新的要害字的潜在影响降到最低程度,我们认为,这对已经拥有代码基的用户非常重要。同时,它答应新功能的使用者获得一流的新增语言功能的体验 — 我们认为在原版语言设计中缺少这些因素。我们将在 2.1.2节中看到 sealed用法的示例。   一个由空格分隔的要害字是与上下文相关要害字的特例。它在字面上将一个与上下文相关的修饰符和一个现存的要害字配对,用空格分隔。这个配对作为一个单独的单位,例如 value class(示例参见 1.1 节),而不是两个单独的要害字。基于现实的因素,这意味着一个重新定义 value 的宏,如下所示:      #ifndef __cplusplus_cli    #define value 不会在一个类声明中去掉 value。假如确实要这么做的话,必须重新定义单元对,编写如下代码:      #ifndef __cplusplus_cli 考虑到现实的因素,这是十分必要的。否则,现存的 #define可能转换由空格分隔的要害字的与上下文相关的要害字部分。  2.托管类型
声明托管类型和创建以及使用这些类型的对象的语法已经大加修改,以提高 ISO-C++类型系统内的集成性。这些更改在后面的小节中详述。委托的讨论延后到 2.3节以用类中的事件成员表述它们 — 这是第 2 节的主题。(有关更加具体的跟踪引用语法介绍的内幕和设计上的主要转变的讨论,请参见附录A:推动修订版语言设计。)

2.1 声明一个托管类类型

在原版语言定义中,一个引用类类型以 __gc要害字开头。在修订版语言中,__gc要害字被两个由空格分隔的要害字 ref class或者 ref struct之一替代。struct或者 class的选择只是指明在类型体中开头未标记部分声明的其成员的公共(对于 struct)或者私有(对于 class)默认访问级别。 类似地,在原版语言定义中,一个 value 类类型以 __value 要害字开头。在修订版语言中,__value 要害字被两个由空格分隔的要害字 value class或者 value struct之一代替。 在原版语言设计中,一个接口类型是用要害字 __interface指明的。在修订版语言中,它被 interface class替代。 例如,下列类声明对   // 原版语法     public __gc class Block { ... };   // 引用类    public __value class Vector { ... };   // 值类    public __interface IMyFile { ... };   // 接口类 在修订版语言设计下等价的声明如下:    // 修订版语法     public ref class Block { ... };    public value class Vector { ... };    public interface class IMyFile { ... }; 选择 ref(对于引用类型)而不是 gc(对于垃圾收集类型)是为了便于更好地暗示这个类型的本质。 2.1.1指定一个类为抽象类型 在原版语言定义中,要害字 __abstract放在类型要害字之前(__gc之前或者之后)以指明该类尚未完成,而且此类的对象不能在程序中创建:   public __gc __abstract class Shape {};    public __gc __abstract class Shape2D: public Shape {}; 在修订版语言设计中,abstract 与上下文相关的要害字被限定在类名之后,类体、基类派生列表或者分号之前。   public ref class Shape abstract {};    public ref class Shape2D abstract : public Shape{}; 当然,语义没有变化。 2.1.2指定一个类为密封类型 在原版语言定义中,要害字 __sealed放在 class 要害字之前(__gc之前或者之后)以指明类的对象不能从以下类继续:   public __gc __sealed class String {};
在 V2语言设计中,与上下文相关的抽象要害字限定在类名之后,类体、基类派生列表或者分号之前(您可以声明一个继续类并密封它。举例来说,String类隐式派生自Object)。密封一个类的好处是答应静态(即在编译时)解析这个密封引用类对象的所有的虚函数调用。这是因为密封指示符保证了 String跟踪句柄不能指向一个可能重载被调用的虚方法实例的派生类。   public ref class String sealed {}; 也可以将一个类既声明为抽象类也声明为密封类。这是一种被称为静态类的非凡情况。这在CLI文档中描述如下: 同时为抽象和密封的类型只能有静态成员,并且以一些语言中调用命名空间一样的方式服务。 例如,以下是一个使用 V1语法的抽象密封类的声明   public __gc __sealed __abstract class State  { public:    static State();    static bool inParamList(); private:    static bool ms_inParam; }; 而以下是在修订版语言设计中的声明:    public ref class State abstract sealed { public:    static State();    static bool inParamList(); private:    static bool ms_inParam; }; 2.1.3 CLI继续: 指定基类 在 CLI对象模型中,只支持公有方式的单继续。但是,在原始语言定义中仍然保留了ISO-C++对基类的默认解释,而无需访问要害字指定私有派生。这意味着每一个 CLI继续声明必须用一个 public要害字来代替默认的解释。很多用户认为编译器似乎过于严谨。// V1:错误:默认为私有派生 __gc class My : File{}; 在修订版语言定义中,CLI继续定义缺少访问要害字时,默认是以公有的方式派生。这样,公有访问要害字就不再必要,而是可选的。虽然这个改变不需要对 V1的代码做任何的修改,出于完整性考虑我仍将这个变化列出。// V2:正确:默认是公有性派生 ref class My : File{};

简介   C++/CLI代表 ISO-C++标准语言的一个动态编程泛型扩展 (dynamic programming paradigm extension)。在原版语言设计 (V1) 中有许多显著的弱点,我们觉得在修订版语言设计 (V2) 中已经修正了这些弱点。本文列举了 V1 版本语言的功能和它们在 V2 版本中的对应功能(假如存在);并指出了其对应功能不存在的构造。对于有爱好的读者,可以查看附录中提供新语言设计的扩展原理。另外,一个源代码级别的转换工具 (mscfront) 正在开发中,而且可能在 C++/CLI的发布版中提供给希望将 V1 代码自动移植到新语言设计的人。   本文分为五个章节加一个附录。第一节讨论语言要害字的主要问题,非凡是双下划线的移除以及与上下文相关和由空格分隔的要害字。第二节着眼于托管类型的变化 — 非凡是托管引用类型和数组。还可以在这里找到有关确定性终结语义 (deterministic finalization) 的具体讨论。关于类成员的变化,例如属性、索引属性和操作符,是第三节的重点。第四节着眼于 CLI 枚举、内部和钉住指针的语法变化。它也讨论了许多可观的语义变化,例如隐式装箱的引入、CLI枚举的变化,和对值类中默认构造函数的支持的移除。第五节有点像大杂烩 — 乱七八糟的杂项。讨论了类型转换符号、字符串字符的行为和参数数组。   1. 语言要害字   原版到修订版语言设计的一个重要转换是在所有要害字中去掉双下划线。举例来说,一个属性现在被声明为 property而不是 __property。在原版语言设计中使用双下划线前缀的两个主要原因是:   1. 这是提供符合 ISO-C++标准的本地扩展的一致性方法。原版语言设计的一个主要目标就是不引入与标准语言的不兼容性,例如新的要害字和标记。这个原因很大程度上也推动了对声明托管引用类型的对象的指针语法的选择。 2. 双下划线的使用,除了兼容性方面的原因之外,也是一个不会对有旧代码基础的用户造成影响的合理保证。这是原版语言设计的第二主要目标。   这样的话,为什么我们移除双下划线(并且引入了一些新的标记)?不是的,这并不代表我们不再考虑和标准保持一致!   我们继续致力于和标准一致。尽管如此,我们意识到对 CLI动态对象模型的支持表现出了一种全新的强大的编程范型。我们在原版语言设计上的经验以及设计与发展 C++ 语言本身的经验使我们确信,对这个新范型的支持需要它自己的高级要害字和标记。我们想提供一个该新范型的一流表达方式,整合它并且支持标准语言。我们希望您会感受到修订版语言设计提供了对这两种截然不同的对象模型的一流的编程体验。   类似的,我们很关心最小化这些新的要害字的对现有代码可能造成的冲击。这是用与上下文相关和由空格分隔的要害字来解决的。在我们着眼于实际语言语法的修订之前,让我们试试搞清楚这两个非凡要害字的特点。   一个与上下文相关的要害字在特定的程序上下文中有非凡的含义。例如,在通常的程序中,sealed 是一个普通标识符。但是,在一个托管引用类类型的声明部分,它就是类声明上下文中的一个要害字。这使得在语言中引入一个新的要害字的潜在影响降到最低程度,我们认为,这对已经拥有代码基的用户非常重要。同时,它答应新功能的使用者获得一流的新增语言功能的体验 — 我们认为在原版语言设计中缺少这些因素。我们将在 2.1.2节中看到 sealed用法的示例。   一个由空格分隔的要害字是与上下文相关要害字的特例。它在字面上将一个与上下文相关的修饰符和一个现存的要害字配对,用空格分隔。这个配对作为一个单独的单位,例如 value class(示例参见 1.1 节),而不是两个单独的要害字。基于现实的因素,这意味着一个重新定义 value 的宏,如下所示:      #ifndef __cplusplus_cli    #define value 不会在一个类声明中去掉 value。假如确实要这么做的话,必须重新定义单元对,编写如下代码:      #ifndef __cplusplus_cli 考虑到现实的因素,这是十分必要的。否则,现存的 #define可能转换由空格分隔的要害字的与上下文相关的要害字部分。  2.托管类型
声明托管类型和创建以及使用这些类型的对象的语法已经大加修改,以提高 ISO-C++类型系统内的集成性。这些更改在后面的小节中详述。委托的讨论延后到 2.3节以用类中的事件成员表述它们 — 这是第 2 节的主题。(有关更加具体的跟踪引用语法介绍的内幕和设计上的主要转变的讨论,请参见附录A:推动修订版语言设计。)

2.1 声明一个托管类类型

在原版语言定义中,一个引用类类型以 __gc要害字开头。在修订版语言中,__gc要害字被两个由空格分隔的要害字 ref class或者 ref struct之一替代。struct或者 class的选择只是指明在类型体中开头未标记部分声明的其成员的公共(对于 struct)或者私有(对于 class)默认访问级别。 类似地,在原版语言定义中,一个 value 类类型以 __value 要害字开头。在修订版语言中,__value 要害字被两个由空格分隔的要害字 value class或者 value struct之一代替。 在原版语言设计中,一个接口类型是用要害字 __interface指明的。在修订版语言中,它被 interface class替代。 例如,下列类声明对   // 原版语法     public __gc class Block { ... };   // 引用类    public __value class Vector { ... };   // 值类    public __interface IMyFile { ... };   // 接口类 在修订版语言设计下等价的声明如下:    // 修订版语法     public ref class Block { ... };    public value class Vector { ... };    public interface class IMyFile { ... }; 选择 ref(对于引用类型)而不是 gc(对于垃圾收集类型)是为了便于更好地暗示这个类型的本质。 2.1.1指定一个类为抽象类型 在原版语言定义中,要害字 __abstract放在类型要害字之前(__gc之前或者之后)以指明该类尚未完成,而且此类的对象不能在程序中创建:   public __gc __abstract class Shape {};    public __gc __abstract class Shape2D: public Shape {}; 在修订版语言设计中,abstract 与上下文相关的要害字被限定在类名之后,类体、基类派生列表或者分号之前。   public ref class Shape abstract {};    public ref class Shape2D abstract : public Shape{}; 当然,语义没有变化。 2.1.2指定一个类为密封类型 在原版语言定义中,要害字 __sealed放在 class 要害字之前(__gc之前或者之后)以指明类的对象不能从以下类继续:   public __gc __sealed class String {};
在 V2语言设计中,与上下文相关的抽象要害字限定在类名之后,类体、基类派生列表或者分号之前(您可以声明一个继续类并密封它。举例来说,String类隐式派生自Object)。密封一个类的好处是答应静态(即在编译时)解析这个密封引用类对象的所有的虚函数调用。这是因为密封指示符保证了 String跟踪句柄不能指向一个可能重载被调用的虚方法实例的派生类。   public ref class String sealed {}; 也可以将一个类既声明为抽象类也声明为密封类。这是一种被称为静态类的非凡情况。这在CLI文档中描述如下: 同时为抽象和密封的类型只能有静态成员,并且以一些语言中调用命名空间一样的方式服务。 例如,以下是一个使用 V1语法的抽象密封类的声明   public __gc __sealed __abstract class State  { public:    static State();    static bool inParamList(); private:    static bool ms_inParam; }; 而以下是在修订版语言设计中的声明:    public ref class State abstract sealed { public:    static State();    static bool inParamList(); private:    static bool ms_inParam; }; 2.1.3 CLI继续: 指定基类 在 CLI对象模型中,只支持公有方式的单继续。但是,在原始语言定义中仍然保留了ISO-C++对基类的默认解释,而无需访问要害字指定私有派生。这意味着每一个 CLI继续声明必须用一个 public要害字来代替默认的解释。很多用户认为编译器似乎过于严谨。// V1:错误:默认为私有派生 __gc class My : File{}; 在修订版语言定义中,CLI继续定义缺少访问要害字时,默认是以公有的方式派生。这样,公有访问要害字就不再必要,而是可选的。虽然这个改变不需要对 V1的代码做任何的修改,出于完整性考虑我仍将这个变化列出。// V2:正确:默认是公有性派生 ref class My : File{};