AutoCAD 3DMAX C语言 Pro/E UG JAVA编程 PHP编程 Maya动画 Matlab应用 Android
Photoshop Word Excel flash VB编程 VC编程 Coreldraw SolidWorks A Designer Unity3D
 首页 > C++

C++和Object Pascal对象模型

51自学网 http://www.51zixue.net

第9章 VCL的C++语言支持
C++Builder的快速应用程序开发(RAD)能力是建立在用ObjectPascal编写的可视组件库(VCL)基础之上的。本章说明ObjectPascal语言的特征、结构及概念如何在C++Builder中实现以支持VCL。

本章的第一部分比较C++和ObjectPascal的对象模型,并说明C++Builder如何组合这两种方法。本章的第二部分说明ObjectPascal语言的结构如何对应转换成C++Builder中的C++结构。包括一些被增加来支持VCL的关键字的扩展的相关细节。这些扩展,如闭合和属性,是独立的支持基于VCL的代码的有用特征。

注意 从TObject派生的C++类是指那些TObject是其最初的、然而并非直接的祖先的类。为保持编译器逻辑上的一致性,这样的类也被称为“VCL风格类”

9.1 C++和ObjectPascal对象模型
C++和ObjectPascal在创建、初始化、引用、拷贝和销毁对象的方法上有些微小的差异。在本节中描述这些细微的差别和它们对C++BuilderVCL风格类的影响。

9.1.1对象本身和实例
在C++中,类的一个实例是一个实际的对象。那个对象能直接被操作,或者通过引用或指针间接访问它。例如,给定一个构造函数中没有参数的C++类CPP_class,下列变量都是该类的有效实例变量:


相反,在ObjectPascal中,一个Object类型的变量总是间接地引用对象。所有对象的内存都动态地被分配。例如,给定ObjectPascal类OP_class:


ref是OP_class类型的对象的一个“引用”。转换到C++Builder代码,将是:


1.区分C++和ObjectPascal的引用
文档中经常会把ObjectPascal类实例变量作为引用提及,但却作为指针来描述它的行为。这是因为它兼有这两者的属性。一个ObjectPascal引用类似C++指针,但有下列的不同:
· 一个ObjectPascal引用是隐式的间接引用(在此情况下更像一个C++引用)。
· 一个ObjectPascal引用不像定义的操作那样有指针运算。
ObjectPascal引用和C++引用比较时,也有类似和不同之处。两种语言的引用都是隐式的间接引用,然而,
· 一个ObjectPascal引用可以被重指,而C++引用不能。
· 一个ObjectPascal引用可以是nil,而C++引用必须指向有效的对象。
有些VCL结构下的设计计划是建立在使用这种类型的实例变量的基础上的。指针是最接近Object Pascal引用的C++语言结构。因此,几乎所有的VCL对象的标识符在C++Builder中都被转换为C++指针。

注意ObjectPascal的var参数类型最接近C++的引用。参见9.2.3节的“Var参数”可获得更多信息。

2.拷贝对象
与C++不同,ObjectPascal没有可支持拷贝对象的内嵌编译器。本节描述这个差别对VCL风格类赋值操作符和拷贝构造函数的影响。

(1)赋值操作符
ObjectPascal赋值操作符(:=)不是一个类赋值操作符(operator=())。操作符赋值拷贝引用,而不是对象。在下列代码中,B和C都指向同一个对象:


这个例子在C++Builder中转换为下列代码:


C++Builder的VCL风格类的赋值操作符遵循ObjectPascal语言的规定。这意味着,下列代码中,在两个dereferenced指针之间的赋值是无效的,因为它们试图拷贝对象而不是指针:


注意 对于VCL风格类,使用C++语法的引用是有效的。例如,下列代码是有效的:


尽管与使用赋值操作符不同,但对于澄清和比较而言,这里提出的语法已经足够类似了。

(2)拷贝构造函数
ObjectPascal没有内嵌的拷贝构造函数。因而,在C++Builder中的VCL风格类也没有内嵌的拷贝构造函数。下例中的代码试图使用一个拷贝构造函数创建TButton指针:


对于VCL类,不能编写依赖于一个内嵌的拷贝构造函数的代码。要在C++Builder中创建VCL风格类对象的一个拷贝,可编写一个成员函数以拷贝对象。另外,VCLTPersistent类的派生类可重载Assign方法以从一个对象拷贝数据到另一个对象。例如,对于包含资源图像的图形类,诸如TBitmap和TIcon通常就会这么做。拷贝一个对象的方式最终由程序员(组件开发者)决定;但需注意一些标准C++使用的拷贝方法对VCL风格类是不适用的。

3.对象作为函数参数
正如前面所讨论的,C++和Object Pascal中的实例变量不是等同的。在将对象作为函数的参数传递时应该记住这一点。在C++中,对象可以通过值、引用或指针传递给函数。在Object Pascal中,当一个对象按值传递给函数时,应记住这个对象参数已经是一个对象的引用了。所以,实际上是引用被按值传递,而不是实际的对象。在Object Pascal中,不能像在C++中一样将实际对象按值传递。VCL风格类对象在传
递给函数时遵循ObjectPascal的规定。

9.1.2C++Builder中VCL类的对象构造
C++和Object Pascal构造对象是不同的。本节概述这一问题并说明C++Builder如何综合这两种方式。

1.C++对象构造
在标准的C++中,构造的顺序先是虚基类,然后是基类,最后是派生类。C++语法使用构造函数初始化列表调用基类构造函数。对象的运行时类型为当前构造函数被调用的类的类型。虚拟方法的分派遵循对象的运行时类型并因此在构造期间变化。
2.Object Pascal对象构造
在Object Pascal中,仅有实例化的类的构造函数确保被调用,然而,仍为基类分配内存。直接基类的构造通过在相应的派生类的构造函数中调用inherited来进行。习惯上,VCL类使用inherited调用(非空)基类构造函数。不过,这并不是语言的要求。对象的运行时类型立即被建立为实例化的类的类型,并且不在基类构造函数被调用时变化。虚拟方法的分派遵循对象的运行时类型并且不在构造期间变化。

3.C++Builder对象构造
VCL风格对象的构造与ObjectPascal对象类似,但适用C++语法。这意味着调用基类构造函数时遵循C++语法,对于所有的非VCL的基类和最直接的VCL父类使用初始化列表。这个VCL基类最先被构造。它使用inherited构造自己的基类,遵循ObjectPascal的方法。因此,VCL基类构造的顺序与C++的相反。然后从最远的祖先到派生类,所有的C++基类被构造。对象的运行时类型和虚拟方法分派也基于ObjectPascal。
图9-1说明了一个VCL风格类实例的构造,MyDerived从MyBase派生,MyBase是TWinControl的一个直接的派生类。MyDerived和MyBase以C++实现。TWinControl是以ObjectPascal实现的VCL类。


注意 到对一个C++程序员来说,构造的顺序似乎是反的,因为对于实际的VCL类,它从最边缘的父类开始一直到TObject,然后构造MyBase,最后构造派生类。
注意 TComponent不调用inherited,因为TPersistent没有构造函数。TObject有一个空的构造函数,它也不被调用。若这些类构造函数被调用,其顺序将遵循图9-1中的顺序(这些类为图中带灰影的部分)。
表9-1总结了C++、ObjectPascal、C++Builder的对象构造模型:
点击放大

<

 

 

 
上一篇:C++&nbsp;Builder&nbsp;运行时包  下一篇:Win32下的结构异常