Object Pascal与C++面向对象特征的对比
Comparisons of Object-Oriented Features between Object Pascal and C++
两江
?
摘要:论述了Object Pascal和C++两种程序设计语言中各自的面向对象特征,并作了一定的对比。
Abstract:The features of the two Object-Oriented programming languages--Object Pascal and C++--are , and also make some contrasts between them.
关键词:面向对象? Object Pascal? C++
Key words:Object-Oriented? Object Pascal? C++
?
一、引言
Delphi是一种优秀的快速开发工具,其核心语言是Object Pascal。Delphi有着许多有点,语言结构严谨,代码优美;编译速度快,超过其他编程工具;强大的数据库程序开发能力,控件非常多;完全可视化;同时又是面向对象的。Delphi的入门和上手非常容易,许多程序员参照例子程序很快就可以写出像样的代码,但是他们却忽略了Object Pascal的面向对象的特征。大部分介绍面向对象的书籍都以C++作为示例语言(当然,现阶段用Java或C#这两种纯面向对象语言来讲授面向对象技术的书籍也在不断出现)。事实上Object Pascal的面向对象特征也是很完备的。
所谓面向对象方法是对现实世界模型化以利于计算机软件的编制的一种方法,它是对现实世界的抽象。面向对象中包括许多概念:类、实例、消息、方法、属性、封装、继承、多态性和重载等。这些概念在Object Pascal和C++中都有相应的体现。
?
二、具体比对
1、类:类是一组具有相同属性和相同操作的对象。以一个银行帐户类为例。
在C++中的定义(以下略作C++):
class TAccount
{
?????? private:
????????????? char UserPSW[8];? //用户密码
?????? protected:
????????????? double Balance;???????????? //帐户余额
?????? public:
????????????? char AccountID[20];???? //帐号
????????????? double GetBalance(char *aID, char *uPSW);????? //得到余额
}
?
在Object Pascal中的定义(以下略作Object Pascal):
TAccount = class
private
?????? UserPSW: String;?? //用户密码
protected
?????? Balance: real;????????? //帐户余额
public:
?????? AccountID: String; //帐号
?????? real GetBalance(aID: String; uPSW: String);??????? //得到余额
end;
可见两者类的定义基本上是相同的。
?
2、实例:一个类的具体的对象
C++:TAccount account1;
Object Pascal:account1: Taccount;
?
3、消息:对象间交互所传递的通信信息
C++:account1.GetBalance(a, b);
Object Pascal:account1.GetBalance(a, b);
实例account1在接收到这消息后,将执行GetBalance操作。
?
4、方法(函数):对象在响应消息后需要执行的操作
如GetBalance验证帐号、密码,再返回余额的实现代码,这是程序语言代码上的具体实现,所以不作具体的比对了。
4.1构造函数、析构函数:构造函数是用来给对象分配空间,给其成员变量赋初值等。析构函数正好相反,是用来给对象释放空间和其它一些扫尾工作。
C++:
class TAccount
{
?????? public:???? //通常构造函数、析构函数均在此部分定义
?????? TAccount(…){…} //构造函数
?????? ~TAccount(){…}?? //析构函数(无任何参数),通常不显式调用
}
?
Object Pascal:
TAccount = class
public
constructor Create(…); virtual;???? //构造器(即构造函数)
destructor Destroy; override; ?????? //析构器(即析构函数)
end;
在新的面向对象语言中如Java、C#,由于引入了垃圾收集(garbage collection)概念,也就没有了析构函数一说。
4.2静态成员函数:
C++:静态成员函数不属于具体对象实例,而是属于整个类共享,调用该函数时需要指定类。
class TAccount
{
?????? public:
?????? static char *BankName ();
}
调用时:TAccount::BankName();
?
Object Pascal:函数默认都是静态(static)的,静态函数在调用时,在编译时决定函数的调用入口。
TAccount = class
?????? Procedure? Draw (amount: real);
end;
TCreditAccount = class
?????? Procedure? Draw (amount: real);
end;
调用时:
var
?????? account1: TAccount;
?????? caccount1: TCreditAccount;
begin
?????? account1:= TCreditAccount.Create;
?????? account1.Draw(100);??? //此处调用的是TAccount的Draw方法
?????? TCredtiAccount(account1).Draw(100);????????????? //此处调用的是TCredtiAccount的Draw方法
?????? account1.Destory;
end;
?
5、属性:类中定义的数据值,也叫做成员变量。类的每个实例都拥有自己的属性值。
例如在‘1、类’中定义的余额(Balance)属性。
?
6、封装:即将类的具体实现包装起来,用户只能通过类提供的接口来访问该类的对象。
6.1访问权限
C++:提供了三种访问权限
public 公有的,公有的成员,可被与该类对象处在同一作用域内的任何函数访问;
protected 保护的,保护的成员只能被所在类和子类成员函数和友元函数访问;
private 私有的,私有的成员只能被该类的成员函数和该类的友元函数访问。
?
Object Pascal:也提供了三种访问权限
public 公有的,公有成员可以被程序代码的任意部分访问;
protected 保护的,保护成员只能被当前类和子类和声明类的单元访问;
private 私有的,私有成员只能在声明类的单元访问。
可以看到Object Pascal中的可访问私有成员的范围比C++中大,只要和该类同一单元即可访问到。另外Object Pascal中没有友元的概念。Object Pascal中还有第四种访问权限published(公布的),它和public的访问权限类似,不同在于它是运行时信息RTTI(runtime type information),RTTI允许程序动态地访问对象的字段和属性,并确定成员函数的入口。Delphi组件中的属性与事件通常都是published的。
6.2自引用指针:顾名思义,是在类内部指向自己的指针,在非静态成员函数中有效。
C++:this->Draw(100);????????????? //Draw是类中的一个成员函数
Object Pascal:self.Draw(100);
6.3友元:一个类的友元函数可以直接访问该类的私有数据。C++中有这一概念,Object Pascal中没有,但是前文提及,同单元内类的私有成员可以相互访问。
C++:??? class TAccount;??????????? //定义向前引用
????????????? class TFAccount
{
?????? friend void func(…);??????????? //友元函数
}
class TAccount
{
?????? friend void func(…);??????????? //友元函数
}
在func方法中可以访问类TAccount和类TFAccount的私有成员。
?
7、继承:在已有类的基础上建立新类,新类可以利用已有类的部分或全部内容,还可以拥有自己的特性,方便了代码的重用。
7.1(单重)继承
C++:??? class TCreditAccount : public TAccount
…
这样就从TAccount类中派生出TCredit类,继承方式是public。继承方式必须是public、private,继承后的权限如下表。
| 父类 | 子类 | ||||||
Public | public | public | ||||||
protected | private | |||||||
private | 不能直接访问 | |||||||
Private | public | private | ||||||
protected | private | |||||||
Private | 不能直接访问 |
?
Object Pascal:TCreditAccount = class(TAccount)
???????????????????? ?…
没有类似C++中多样的继承方式,它的继承原则是父类的public和protected成员仍然为public和protected的,父类的private元素不能在子类中访问。但是,如果父类子类在同一单元,其所有成员均能访问到。
7.2多重继承
一个类可能需要继承多个类,从而引出了多重继承。
C++:??? class TAccountA;????????? //定义省略
????????????? class TAccountB;????????? //定义省略
????????????? class TAccountC:public TAccountA, public TAccountB????? //类C继承了A和B
????????????? …
?
Object Pascal:使用接口(interface)实现多重继承,可以将需要多重继承的方法定义在接口中,然后定义子类时让它继承父类和接口。
IBank = interface
?????? procedure? square();
end;
TCreditAccount = class (TAccount, IBank)
…
?
8、多态性:派生类对象可以像基类对象一样使用,同样的消息既可以发送给基类对象也可以发送给派生类对象。
8.1虚函数:基类中定义的虚函数,派生类中将重新定义。
C++:??? class TAccount
????????????? {…
???????????????????? virtual void square ();
}
class TCredtiAccount : public TAccount
{…
?????? void square (){…}
}
?
Object Pascal:???? TAccount = class
??????????????????????????? ?????? procedure square; virtual;
??????????????????????????? end;
??????????????????????????? TCreditAccount = class(TAccount)
?????????????????????????????????? procedure square; override;
??????????????????????????? end;
8.2抽象方法:基类方法不定义方法的实现,子类需要定义之。
C++:纯虚函数,即虚函数没有定义函数的实现,子类必须给出自己的定义,上例既是。
?
Object Pascal:基类中procedure square; virtual; abstract;
?????????????????????? 子类中 procedure square; override;
?
9、重载:类中相同的函数名,参数表不同,实现不同的操作。
C++:void Draw(double amount)
????????? void Draw(char curType, double amount)
?
Object Pascal:procedure Draw(amount: real); overload;
?????????????????????? procedure Draw(curType: Char; amount: real); overload;
?
三、结束语
通过以上的对比可知,Object Pascal中的面向对象特征是相当完备的,大体上与C++类似,小部分有区别。本文中还有一些特性没有提及,比如C++中有的操作符重载,Object Pascal中的动态方法等,这些都是各自特有,所以就没有作对比了。总之,Object Pascal和C++各有千秋,如何充分利用其提供的面向对象特性,设计出优秀的面向对象程序,才是我们的目标。
?
参考文献
[1] Marco Cantu Delphi6从入门到精通[M]. 北京:电子工业出版社,2002-04
[2] 张海藩,牟永敏 面向对象程序设计使用教程[M]. 北京:清华大学出版社,2002-06
[3] 李陶深,赵文静 面向对象程序设计与方法[M]. 北京:武汉理工大学出版社,2003-08
?