请问如何在Delphi中利用Object Pascal实现类似C++中的模板类的功能。(100分)

  • 主题发起人 主题发起人 starfish
  • 开始时间 开始时间
S

starfish

Unregistered / Unconfirmed
GUEST, unregistred user!
比如在C++中,
template <T>
T abc(T a, T b)
{return a+b}
如何在Pascal中实现?
 
delphi没戏,
没有就是没有了,想也没用
 
好象是没有
很不爽:-(
 
对于模板类来讲,Delphi不需要。因为C++不是唯一基类继承,不是一棵继承树,所以
需要模板类的出现来实现容器相关的类,用来对不同类型的类实现存储。而对Delphi来讲,
他所有的类都继承于一个统一的基类object类,所以在容器等方面,不需要再引进模板类
来实现了。
 
Delphi 的 Object Pascal 语言不支持类似 C++ 的模板,而且据我所知其他的
各种版本 Object Pascal 编译器都不支持模板。因为 Object Pascal 语言的
面向对象结构与 C++ 不完全相同。对于 Object Pascal 来讲,模板是多余的,
根本不需要引入!
 
其实C++也并不需要模板。采用模板,编出的程序要清楚一些,不采用模板,也完全可以获得
相似的结果。象JAVA的收集类,就实现了C++中STL(标准模板库)的功能。而JAVA语言只能算
是C++的子集。
DELPHI不引进模板的思想应该和DELPHI不引入多重继承的思想是一样的。尽管有用,但将
较大的增加编程的难度和开发编译器的难度。象DELPHI和JAVA这种不断发展的语言,还是
保持一个精简的内核较好。
 

santgan兄弟,呵呵,C++同java仅仅是近似而已,java不是C++的子集,只有c语言才算是
c++的子集。java同object passcal更像,都是单根继承树,都有统一的祖基类,都不能
多重继承,也都不用引进模板类的概念。

其实,在模板类引进C++之前,C++都是采用多重继承的方式实现容器类等一些关键概念,
因为多重继承太过于复杂,容易导致各方面的错误,为了解决多重继承的不足,C++后来才
逐渐引进了模板类来代替多重继承。这些方面相关的内容,可以在《Think in C++》中看
到。但是模板类的概念,也相对复杂一些。

再到后来,java语言编写的时候,作者参考了c++、object passcal等很多语言,并作了许
多改进,简化了C++的很多编程实现,取消了C++中的多重继承,也建立自己的统一基类object
 
看一看 hwz 的大作(好像在chinasp):

object pascal不支持对象模板。因为对象模板不过是宏的语言实现而已(宏本身不是
c/c++的语言特性)。

至于macro和.h则应该说是垃圾特性,只是由于兼容性的考虑才保留下来的。ansi/iso
c/c++规范中明确建议:“不要使用macro和.h,应该使用程序中的常量定义和函数替
代”。因为macro和.h不是c/c++的语言特性(这是真的!),没有明确统一的语法定义。
还会导致编译速度降低,另外由于macro在每个使用的地方被展开(不是调用),大量使
用macro会使生成的代码臃肿。

本人虽然也精通C、C++ ,但对上述观点持赞同态度。
 
嗯,后面这几位说得还可以嘛!
前面的,听到了?
哈哈哈...
 
XiDao兄,看来你是JAVA的狂战士了,佩服佩服!
但我仍然坚持Java在语言本身上是C++的子集。大家现在都知道JAVA的应用范围比较广泛,
但这并不是因为其语言本身的特点。而是由一些外部支持工具所做到的。比如servlet,
jsp等。而其语言本身,并没有超出C++的概念。java和C++是否是子集的关系不应该从
细看考虑,而应该从语言的特性考虑。并不是java修改了几个关键字就可以说java超出了
C++的思想范畴。
事实上,JAVA语言所以运用广泛,也正是因为去掉了C++的一些复杂特性。JAVA比C++简单
好学这一点是确实存在的。JAVA的类体系和DELPHI很象,事实上,用C++完全可以实现
JAVA和DELPHI的类库体系,如C++Builder就是这一事实的证明。但是由于C++本身已经具有
了多种实用的类库如STL以及其他众多厂商开发的类库,C++很难形成大众所公认的如JAVA
和DELPHI的单一体系类库。
对于C++来说,光辉的历史已经成了一个包袱。这也正是现阶段各种面向对象语言纷呈的一
个因素。
 
???刚夸了你们两句就不行了? :-)

Java最多最多只能说语法上是C++的子集(如果认为那些关键字没带来什么本质革新的话)
而对象结构是与Delphi类似的,决非C++可比。
BCB的对象结构使用的是Object Pascal的体系,代码都是OP的,C++根本写不出来,
“用C++完全可以实现JAVA和DELPHI的类库体系”实在是大错特错了
 
我不可能用C++把VCL或Java类库重写一遍,也不想写。BCB自带的控件都是用的DELPHI的OP
代码,这点确实没错。但我认为Borland这么做的原因在于没有必要用C++重写VCL,首先是
没有这个必要,继承可复用的资源是软件界最基本的常识;其次,直接使用VCL代码,能够
保持与Delphi的兼容性,可以利用已有的众多OP源码的Delphi控件,从策略上说这么做是
完全正确的。使用BCB完全可以编写C++语言的控件,用Delphi能完成的任务,使用BCB也同
样能够完成。
我并不想说明BCB和Delphi的优劣,这个问题是没有意义的。我认为这两个开发工具都是非
常优秀的,能够大幅度提高程序员的工作效率。但是就语言方面来说,OP并没有超过C++的
地方(细节除外)。
 
santgan:
我们在这里并没有讨论BCB与delphi,而是C++与OP,因此我们的目的并不矛盾。

但是你说C++可以重写VCL,这确实是错误的。说白了,BCB的用户首先是Op的用户,
其次才是C++的用户(除非你不使用VCL)。就象Java一样,不过是语法上面与C++一致而已,
本质上是完全不同的。

鉴于老左也在上面,我要是再说一次为什么C++不能写VCL,难免被人说是“卖弄”,
其实老左以前的想法和你一样的,不如就让他现身说法一次如何? :-)

(老左呀,不要怪我拉人垫背,我也是没办法,单练总比群殴效果差不是?^_^)
 
WK,岂有此理……
本来正想写个贴子让一刀现身说法的,谁知晚了一步……
的确,我以前也认为OP是C++的子集,OP只是省略了C++的一些高级特性
再用pascal语法表现出来的C++(见我以前的一些贴子),但后来发现我错了……
OP固然砍掉了C++一些复杂的东西,但也加入了一些C++没有的东西(JAVA也如此),
因此说OP或Java是C++的子集是不正确的……
C++在被创造的时候,由于考虑到向下兼容性,牺牲了一些OOP的东西,
这一点在《Thinking in Java》曾经讨论过,建议楼上的老兄读一下……
BCB使用D写的VCL,并不是其他原因,而是用C++的确写不出来……
至于令人信服的证据么,一刀兄,你上……
其实这种误解普遍存在,所以我认为是应该详细说明一下的时候了……
 
C++ 发展到 C++Builder 这一步,为了兼容 Delphi/Object Pascal 的面向对象
体系结构已经对 C++ 做了很大的修改。虽然 C++Builder 完全符合 ANSI C++ 标准,
但是 ANSI C++ 标准只是 C++Builder 的一个子集。BCB 的最大特点应该是在 C++
的面向对象中增加了“属性”功能和类对象级别的 RTTI 运行时参考信息支持,以
扩展关键字 __property 以及特殊的 TClass 指针类出现。属性的出现才应该说是
面向对象的完整体现。而这一点 Delphi/Object Pascal 早在 1994 年就已经引入
了。VB 虽然更早一些,但那时的 VB 还算不上是一个 OOP 语言(准 OOP)。既然
软件设计发展到 RAD 可视化这一步是必然的,那么面向对象程序设计技术也会随着
一起发展。OOP 与 RAD 的结合要求 OOP 语言支持组件模型机制以及 RTTI 运行时
信息能力。而“属性”这一 OPP 新特性是必不可少的。Delphi/Object Pascal 是
在编译器级别完整支持这些的,由于这些以及 Object Pascal 的语言结构,使得
VCL 在构造上采用的是单一继承。不知道大家记不记得 Borland 的 OWL 类库?
Borland C++ 的 OWL 库采用的是多重继承,而 Borland Pascal for Windows 采用
的是单一继承方式写的。可以这么说,在建立非 COM/DCOM/COM+ 类上,OP 不需要
多重继承,那会给编译器带来不必要的负担,同时也会加重程序员的负担。OP 的多
重继承是采用 interface 接口实现的,但是这和 C++ 的多重继承又不完全相同。
OP 的多重继承用于实现多个 COM 接口,它是 VCL 类与 COM 接口类的复合。而
COM 接口只提供方法(函数)给外部,其他的信息是不能暴露的!Java 的出现也
似乎证明了 OOP 语言的发展方向。单一继承看起来好像让人觉得功能上不如多重继
承强大,但是单一继承的内涵是丰富的,它有很多重继承没有的优点,而这些优点
足以弥补单一继承的薄弱之处。君不见 BCB 的类如果不从 TObject 派生,就不会具备
真正意义上的 RTTI 运行时参考信息能力了。RTTI 到底是什么?举个例子,我们在
Delphi 中,as 和 is 操作符实在是太方便了:
procedure TForm1.Foo(Sender: TObject);
...
if Sender is TEdit then
...
with Sender as TEdit do
begin
...
end;
...
而这些事件函数在声明时都带有 of Object 语法,说明它们携带有 RTTI 信息。
而 BCB 中相应的事件函数指针必须家上扩展关键字修饰符 __closure 才能使函数
指针带有 RTTI 。这与普通的 C++ 类函数指针是完全不同的。上面的例子在 BCB
中变为 if (Sender->ClassType == __classid(TEdit)) ... 注意这里的 __classid
关键字也是新的!!这样的扩展还很多,可以查阅一下 BCB 的帮助。所以对标准
C++ 很熟悉的人一开始可能会被 BCB 弄糊涂。
(TEdit *)Sender->... 你当然也可以用 dynamic_cast 关键字,但在编译器内部
这和前面一种方式没有两样。所以说,用 C++ 建立 VCL ,如果不对 C++ 进行全面
扩展的话,是不可能做出现在这样的 VCL 的,其结果只能是 VC++ 的 MFC 和过去的
Borland C++ OWL。其实,VC 也有很多晦涩难懂的语法,不过基本上都是宏和模板,
VC 是不支持 BCB 的新语法的,也不支持对象属性和类对象级 RTTI。这是造成了
VC 设计模式仍然停留在代码设计方式没有引进真正的可视化的一个主要原因。
所以,对于 Object Pascal 语言,没有必要追求 C++ 的多重继承,因为 C++ 其实
正在处于一个重要的转型期,一方是保守的标准 C++ 维护者,另一方是求变改革者。
如果你是个 Object Pascal ,你应当庆幸,用好你的 Object Pascal ,相信它是绝对
不比 C++ 弱的!如果你是 C++ 程序员,还是要学好标准 C++,但是你还要掌握 C++
的新的扩展特性,因为这很有可能是将来的 C++ 要具备的。我的感觉是,C++ 把很多
本来简单的东西弄的复杂了。
 
其实我刚刚想了一下,
“C++不能写VCL”这一论断其实不能说绝对正确,(我够两面三刀吧! :-)
因为从广义上讲,只要形式上类似VCL,实质上又能完成VCL的功能,
则也可以算作“写出了VCL”。因此,只能说C++不能以OP的方式写出VCL,
从实践上看,区别可能就是更麻烦,或者封装得不够好。

因此,我们应该再进一步,把VCL也抛弃开,直接讨论这两个语言的异同。
(这也是我文章中所列前提条件之一 -- 文章遥遥无期,老拿来说事,真是惭愧 ^_^)
因此,更准确的说法应该是,OP确实引入了很多新的特性,当然都是在面向对象方面,
或者用santgan的话:“就语言方面来说,OP确实有超过C++的地方(包括细节)” :-)

不知道大家是否看过“悟透Delphi”的若干章节,很多地方都有转贴,论坛上也有,
只要看过,再对比thinking in C++中的相应内容,就应该了解OP的本质了。
因此,我在这里还是不说了吧...

ps: 写这段文字时候还没看到Phoenix2000的贴子,感觉上和我们是一伙的 :-)
 
好大的棉花糖啊!
哈哈
从语言本身来说我最喜欢的还是java,有OP的特性又有C++的语法
可惜不能拿来写桌面程序(别跟我抬杠……)
 
也许应该期待C#?
 
JAva的事件机制不同于Delphi,你用着可要当心哟,
M$就为这个(主要原因之一)成了被告,最后放弃了Java的...

从这个角度讲,C#与Delphi更接近 -- 别忘了是谁设计的 :-)
 
能够和温柔一刀和左轻候等数位高人讨论问题,真是感到非常的荣幸。

不过从上面说的,我没有看出OP优越特性的真凭实据来。我认为OP的interface应该是对
C++中的纯虚类的一个继承。而属性只是对函数调用的隐藏,我认为JavaBeans的属性机制
就揭示了这一点。我同意使用属性非常方便,但使用函数调用也并无不可。当然,对于
初学者来说,使用属性是非常容易上手的。到真正开发程序的时候,采用属性表示还是
函数封装都不影响程序的开发效率。其次,我认为C++理所当然也可以实现单继承树的类
库,不可能有了多重继承的机制就非使用多重继承不可。

至于运行时类型信息,C++中也早就有了。VC、BC和BCB中都有,并不是Delphi独有的,用
来作为Op相对于C++的优越性似乎不妥。
 
后退
顶部