设为首页 加入收藏

TOP

将程序从托管扩展 C++ 迁移到 C++/CLI(1)
2013-10-06 23:44:13 】 浏览:196
Tags:程序 托管 扩展 迁移 /CLI

简介

 

C++(www.cppentry.com)/CLI代表 ISO-C++(www.cppentry.com)标准语言的一个动态编程(www.cppentry.com)泛型扩展 (dynamic programming paradigm extension)。在原版语言设计 (V1) 中有许多显著的弱点,我们觉得在修订版语言设计 (V2) 中已经修正了这些弱点。本文列举了 V1 版本语言的功能和它们在 V2 版本中的对应功能(如果存在);并指出了其对应功能不存在的构造。对于有兴趣的读者,可以查看附录中提供新语言设计的扩展原理。另外,一个源代码级别的转换工具 (mscfront) 正在开发中,而且可能在 C++(www.cppentry.com)/CLI的发布版中提供给希望将 V1 代码自动移植到新语言设计的人。

 

本文分为五个章节加一个附录。第一节讨论语言关键字的主要问题,特别是双下划线的移除以及与上下文相关和由空格分隔的关键字。第二节着眼于托管类型的变化特别是托管引用类型和数组。还可以在这里找到有关确定性终结语义 (deterministic finalization) 的详细讨论。关于类成员的变化,例如属性、索引属性和操作符,是第三节的重点。第四节着眼于 CLI 枚举、内部和钉住指针的语法变化。它也讨论了许多可观的语义变化,例如隐式装箱的引入、CLI枚举的变化,和对类中默认构造函数的支持的移除。第五节有点像大杂烩乱七八糟的杂项。讨论了类型转换符号、字符串字符的行为和参数数组

 

1. 语言关键字

< xml:namespace prefix = o /> 

原版到修订版语言设计的一个重要转换是在所有关键字中去掉双下划线。举例来说,一个属性现在被声明为 property而不是 __property。在原版语言设计中使用双下划线前缀的两个主要原因是:

 

1.

这是提供符合 ISO-C++(www.cppentry.com)标准的本地扩展的一致性方法。原版语言设计的一个主要目标就是不引入与标准语言的不兼容性,例如新的关键字和标记。这个原因很大程度上也推动了对声明托管引用类型的对象的指针语法的选择。

2.

双下划线的使用,除了兼容性方面的原因之外,也是一个不会对有旧代码基础的用户造成影响的合理保证。这是原版语言设计的第二主要目标。

 

这样的话,为什么我们移除双下划线(并且引入了一些新的标记)?不是的,这并不代表我们不再考虑和标准保持一致!

 

我们继续致力于和标准一致。尽管如此,我们意识到对 CLI动态对象模型的支持表现出了一种全新的强大的编程(www.cppentry.com)范型。我们在原版语言设计上的经验以及设计与发展 C++(www.cppentry.com) 语言本身的经验使我们确信,对这个新范型的支持需要它自己的高级关键字和标记。我们想提供一个该新范型的一流表达方式,整合它并且支持标准语言。我们希望您会感受到修订版语言设计提供了对这两种截然不同的对象模型的一流的编程(www.cppentry.com)体验。

 

类似的,我们很关心最小化这些新的关键字的对现有代码可能造成的冲击。这是用与上下文相关和由空格分隔的关键字来解决的。在我们着眼于实际语言语法的修订之前,让我们试试搞清楚这两个特别关键字的特点。

 

一个与上下文相关的关键字在特定的程序上下文中有特殊的含义。例如,在通常的程序中,sealed 是一个普通标识符。但是,在一个托管引用类类型的声明部分,它就是类声明上下文中的一个关键字。这使得在语言中引入一个新的关键字的潜在影响降到最低程度,我们认为,这对已经拥有代码基的用户非常重要。同时,它允许新功能的使用者获得一流的新增语言功能的体验我们认为在原版语言设计中缺少这些因素。我们将在 < xml:namespace prefix = st1 ns = "urn:schemas-microsoft-com:office:smarttags" />2.1.2节中看到 sealed用法的示例。

 

一个由空格分隔的关键字是与上下文相关关键字的特例。它在字面上将一个与上下文相关的修饰符和一个现存的关键字配对,用空格分隔。这个配对作为一个单独的单位,例如 value class(示例参见 1.1 ),而不是两个单独的关键字。基于现实的因素,这意味着一个重新定义 value 的宏,如下所示:

 

   #ifndef __cplusplus_cli

   #define value

不会在一个类声明中去掉 value。如果确实要这么做的话,必须重新定义单元对,编写如下代码:

 

   #ifndef __cplusplus_cli

考虑到现实的因素,这是十分必要的。否则,现存的 #define可能转换由空格分隔的关键字的与上下文相关的关键字部分。

 

2.托管类型

声明托管类型和创建以及使用这些类型的对象的语法已经大加修改,以提高 ISO-C++(www.cppentry.com)类型系统内的集成性。这些更改在后面的小节中详述。委托的讨论延后到 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++(www.cppentry.com)对基类的默认解释,而无需访问关键字指定私有派生。这意味着每一个 CLI继承声明必须用一个 public关键字来代替默认的解释。很多用户认为编译器似乎过于严谨。

// V1:错误:默认为私有派生 
__gc class My : File{}; 

在修订版语言定义中,CLI继承定义缺少访问关键字时,默认是以公有的方式派生。这样,公有访问关键字就不再必要,而是可选的。虽然这个改变不需要对 V1的代码做任何的修改,出于完整性考虑我仍将这个变化列出。

// V2:正确:默认是公有性派生 
ref class My : File{}; 

内容导航

】【打印繁体】【投稿】【收藏】 【推荐】【举报】【评论】 【关闭】 【返回顶部
上一篇Visual C++对大型数据文件的读取 下一篇Python与C++ 程序的简单实例对比

最新文章

热门文章

Hot 文章

Python

C 语言

C++基础

大数据基础

linux编程基础

C/C++面试题目