| ObjectPascal数据类型和语言概念的支持 B |
| 责任编辑:育鹰 更新日期:2005-8-6 |
| | 9.2.7 缺省参数 ObjectPascal编译器现在对于构造函数接受了缺省参数以适应C++。与C++不同,ObjectPascal构造函数可有相同数目和类型的参数,因为它们名字唯一。在这种情况下,使用缺省参数以在C++头文件生成时区别ObjectPascal构造函数。例如,对一个类TInCompatible,ObjectPascal构造函数可能是:
若没有缺省参数,这两个构造函数转换到C++会是下列模糊的代码:
对类TCompatible使用缺省参数,Object Pascal构造函数为:
在C++Builder中转换到下列不含糊的代码:
注意 关于缺省参数的主要的问题是D C C 3 2去除缺省参数的缺省值。不去除缺省值将导致是否根本没有缺省值的歧义。当使用VCL 类时或使用第三方的组件时,应该记住这点。
9.2.8 运行时类型信息 ObjectPascal有其处理的语言结构。有些有C++的对应。这些在表9-3中列出:
在表9-3中,ClassName是TObject的一个方法,返回包含对象实际类型名的一个字符串,不考虑声明的变量类型。在TObject中提供的其他RTTI方法没有C++的对应。
这里列出的都是公共的: · ClassInfo 返回指向运行时类型信息列表(RTTI)中的对象类型的指针。 · ClassNameIs 决定一个对象是否为特定类型。 · ClassParent 返回类的直接父类的类型。对于TObject,因为TObject没有父类,ClassParent返回nil。它通过InheritsFrom方法及is和as操作符使用。 · ClassType 动态决定对象的实际类型。它通过ObjectPascalis和as操作符被内部使用。 · FieldAddress 使用RTTI获得发布的字段的地址。它被流系统内部使用。 · InheritsFrom 决定两个对象的关系。它通过ObjectPascalis和as操作符被内部使用。 · MethodAddress 使用RTTI获取一个方法的地址。它被流系统内部使用。 TObject的这些方法中的一些主要由编译器或流系统内部使用。
9.2.9 未映射的类型 1. 6字节Real类型 旧的ObjectPascal的6字节浮点格式现在被称为Real48。旧的Real类型现在是double。C++中没有Real48类型的对应。因而,应该不将包括这种类型的ObjectPascal代码与C++代码一起使用。否则,头文件生成器将产生警告。
2. 数组作为函数的返回类型 在ObjectPascal中一个函数能将数组作为一个参数获取,或作为一种类型返回。例如,一个返回80个字符的数组的函数GetLine的语法是:
C++没有这个概念的对应。在C++中,数组不允许作为函数的返回类型。C++也不允许数组作为函数的参数类型。尽管VCL没有任何属性值是数组,但ObjectPascal语言确实允许这样做。因为属性能使用Get和Set这两种读和写的方法获取和返回属性值的类型,所以在C++Builder中不能有数组类型的属性。
注意 数组属性,它在ObjectPascal中也是有效的,不像在C++中是一个问题,因为Get方法将索引值作为一个参数获取,Set方法返回类型由数组包含的一个对象。有关数组属性的更多信息,参见41.4.5节。
9.2.10 关键字扩展 本节描述在C++Builder实现的、ANSI适用的、用以支持VCL的关键字扩展。关于C++Builder中关键字和关键字扩展的列表,参见联机帮助。
1.__classid __classid操作符被编译器使用以生成指向特定的classname列表的指针。这个操作符被用来从一个类获得元类。 语法:__classid(classname) 例如,__classid用于注册属性编辑器,组件,和类,并可用于TObject的InheritsFrom方法。下列代码说明创建从TWinControl派生的一个新组件时使用__classid:
2.__closure __closure关键字被用来声明一个特殊类型的指针指向成员函数。不同于一般的C++成员函数指针,闭合包含对象指针。 在标准的C++中,可把一个派生类的实例分配给基类指针;然而,不能把一个派生类的成员函数分配给基类成员函数指针。 下列代码说明这种情况:
然而,__closure语言扩展允许在C++Builder中这么做。闭合将指向成员函数的指针与指向类实例的指针联系起来。当调用相联的成员函数时,指向类实例的指针被作为this指针使用。闭合的声明与函数指针的声明一样,只是在被定义的标识符前增加__closure关键字。例如:
闭合在C++Builder中与事件一起使用。
3.__property __property关键字在类声明中声明属性。属性只能在类中被声明。对于属性数组(当<propdimlist>被使用时),数组的索引可以是任何类型。 语法:
属性有一些特征可将它们与数据成员区分开来。 属性可以: · 通过一个标识符(属性)连接到读或写方法 · 为属性设置缺省值。 · 存储在一个窗体文件中。 · 扩展一个在基类中被定义了的属性。 关于属性的更多信息,参见第41章。
4.__published 如果类在组件面板上,__published关键字指定在该节的属性在对象观察器中被显示。只有从TObject派生的类能有__published节。 发布的成员的可见性规则与公共的成员相同。在发布和公共的成员之间唯一的差别是为数据成员和在__published节声明的属性生成的ObjectPascal风格的运行时类型信息(RTTI)。RTTI可使应用程序能够动态地查询数据成员,成员函数和未知类型的属性。
注意 在__published节不允许有构造函数或析构函数。属性、ObjectPascal内在的或VCL派生的数据成员、成员函数及闭合都允许在__published节中。在__published节定义的字段必须有一种类类型。在__published节定义的属性不能是数组属性。在__published节定义的属性的类型必须是顺序类型,real类型、字符串类型、小集合类型、类类型或方法指针类型。
9.2.11__declspec关键字扩展 __declspec关键字扩展的一些参数为VCL提供语言支持。这些参数在下面列出。declspec参数和它们的组合的宏在sysmac.h中被定义。在大多数情况中不需要指定这些。当确实需要增加它们时,应该使用宏。
1.__declspec(delphiclass) delphiclass参数用于从TObject派生的类的声明。这些类将遵循下列VCL兼容性被创建: · VCL兼容的RTTI。 · VCL兼容的构造函数/析构函数行为。 · VCL兼容的异常处理。
一个VCL兼容的类有下列限制: · 不允许虚基类。 · 不允许多重继承。 · 必须使用全局的new操作符动态地分配。 · 必须有一个析构函数。 · 拷贝构造函数和赋值操作符对于VCL派生类不会是编译器生成的。 如果编译器需要知道类是从TObject派生的,从ObjectPascal转换的类声明将需要这个修饰符。
2.__declspec(delphireturn) delphireturn参数只在C++Builder中被VCL内部使用。它用于C++Builder创建的类的声明,这些类用于支持那些没有原本的C++类型的ObjectPascal内嵌的数据类型和语言结构。包括Currency、AnsiString、Variant、TDateTime及Set。delphireturn参数将C++类标记为在作为函数调用的参数和返回值方面是VCL兼容处理的。当ObjectPascal和C++需要按值传递一个结构给函数时,需要使用这个修饰符。
3.__declspec(dynamic) dynamic参数被用于动态函数的声明。动态函数仅存储在定义它们的对象的vtables中,而不是在派生vtables中,除此之外都与虚拟函数类似。如果调用一个动态函数,而函数没在对象中定义,其祖先的vtables被寻找直到函数被发现。动态函数只对从TObject派生的类有效。
4.__declspec(hidesbase) 当移植ObjectPascal的虚拟和重载的函数到C++Builder时,hidesbase参数维护ObjectPascal程序语义。在ObjectPascal中,基类的虚拟函数能以相同名字的函数在派生类出现,但是它是一个新的函数,与原来的一个没有显式关系。编译器使用在sysmac.h定义的HIDESBASE宏,指定这些类型的函数声明是完全独立的。例如,如果一个基类T1声明一个虚拟函数func,它没有参数,同时它的派生类T2以相同的名字声明了一个函数,DCC32-jphn将使用下列原型生成一个HPP文件:
若没有HIDESBASE声明,C++程序语义指出虚拟函数T1::func()被T2::func()重载。
5.__declspec(package) package参数指示定义类的代码可被编译到包中。当在IDE创建包时,这个修饰符由编译器自动生成。关于包的更多信息,参见第10章。
6.__declspec(pascalimplementation) pascalimplementation参数指出定义类的代码以ObjectPascal实现。这个修饰符在一个带有.hpp扩展名的ObjectPascal可移植头文件中出现。 |
|
| 上一篇文章: C++ 异常处理 B |
| 下一篇文章: C++ Builder 运行时包 |
|
|
|
|