小弟的级别不够不能给更多的分来求教大家!请各位见谅!
我在学习和使用了Delphi一年之后,突然感到很是困惑,C++和Delphi的本质区别是什么呢?
我原来主要是用C做一些驱动的开发,对C++还不是很了解。在这里不是想争论孰优孰劣,只是想从语言的角度对比一下C++和Delphi/OOP。请各位高手赐教!
98 个解决方案
#1
C++支持多继承,Delphi不支持,你看看设计模式吧,很有帮助的,不过小程序很难体现优点的。
#2
我把查询模块都封装成了class,当然是符合流程的了,delphi编写的,
vc编写人事管理系统的时候,个别的class都写成了抽象类,感觉还行,其他几个人都在继承继续编写。
vc编写人事管理系统的时候,个别的class都写成了抽象类,感觉还行,其他几个人都在继承继续编写。
#3
关注
#4
我以前也是用VC的,现正学delphi,对这个问题也较感兴趣。我觉得应从两个方面看,一是object pascal与c++比较,C++更灵活,它支持操作符重载、多继承和模板,因此可实现泛型编程如WTL、STL等。pascal不支持操作符重载和模板,它的接口机制可实现多继承相似的东西。这并不是说c++比pascal更强大,从编程角度讲,没有彼此不能实现的算法。二是从开发环境来讲,DELPHI 比VISUAL C++ 的组件封装更全面、更简洁,因些更适合快速开发应用程序。VC涉及的低层东西较多,开发出的程序更稳健更紧凑,手工代码较多。因此更适合作低层工作。当然,只要你原意,两者可以做所有的WINDOWS平台上的开发,只是速度和效率不一样而已。这就看我们具体要做什么工作了。另外我个人的感受是C++语法更简单,msdn更是在线帮助中的精品,如果项目时间允许,慢一点也原意用它。
#5
delphi实用
#6
Delphi所有的类都必须从TObject继承下来的~~ //这点我不太喜欢哦~~
而C++则没有这个限制~~
C是由汇编演变过来的,是高级语言中最接近机器指令的语言~~
Pascal则是为了教学而设计的,初衷是培养程序员严谨和良好的编程风格~~
网上流传着:真正的程序员用C、聪明的程序员用Delphi~~
其实是废话,
真正的程序员不管用什么还是真正的程序员~~
聪明的程序员不管用什么还是聪明的程序员~~
:)
而C++则没有这个限制~~
C是由汇编演变过来的,是高级语言中最接近机器指令的语言~~
Pascal则是为了教学而设计的,初衷是培养程序员严谨和良好的编程风格~~
网上流传着:真正的程序员用C、聪明的程序员用Delphi~~
其实是废话,
真正的程序员不管用什么还是真正的程序员~~
聪明的程序员不管用什么还是聪明的程序员~~
:)
#7
zswang(伴水清清)的一针见血
#8
还是摆脱语言的困惑吧.
全世界的人,用什么语言都可以交流,难道你能说
哪种语言先进,哪种语言落后.
哪种语言好,哪种语言不好?
全世界的人,用什么语言都可以交流,难道你能说
哪种语言先进,哪种语言落后.
哪种语言好,哪种语言不好?
#9
Delphi所有的类都必须从TObject继承下来的//这点我非常喜欢...嘻嘻
#10
有很多。PASCAL的语法也比较严格的
#11
to zswang(伴水清清)
你错了,并不是非要从TObject继承下来
你可以测试下!
TClass = object
public
class procedure Create;
end;
这样的声明是可以的,它并不是从TObject继承的
一般写法为:
TClass= class //这里省略了TObject 但实际是从TObject继承
end;
但是象上面使用object来定义的类怎么使用,我还不太清楚!
你错了,并不是非要从TObject继承下来
你可以测试下!
TClass = object
public
class procedure Create;
end;
这样的声明是可以的,它并不是从TObject继承的
一般写法为:
TClass= class //这里省略了TObject 但实际是从TObject继承
end;
但是象上面使用object来定义的类怎么使用,我还不太清楚!
#12
TO :楼上
这个就合C++一样,不再堆上分配!也不用调用TXXXX.Create
当你
Var
时,就直接调用构造函数了
这个和Turbo Pascal 5.5+ 是一样的!
这个就合C++一样,不再堆上分配!也不用调用TXXXX.Create
当你
Var
时,就直接调用构造函数了
这个和Turbo Pascal 5.5+ 是一样的!
#13
Test = object
a:integer;
b:integer;
function geta:integer;
end;
function test.geta:integer;
begin
result:=a;
end;
var aa:Test;
aa.a:=100;
aa.geta;
...
我一直这样用,只是不要使用virtual 方法
a:integer;
b:integer;
function geta:integer;
end;
function test.geta:integer;
begin
result:=a;
end;
var aa:Test;
aa.a:=100;
aa.geta;
...
我一直这样用,只是不要使用virtual 方法
#14
to zwjchina:
虽然对象类型确实是早期面向对象使用的类型~~
但对象类型和类类型是不同类型 :)~~
所以你说我错,我可不同意~~
对象类型不需要构造和析构就可以使用,更象是记录类型~~
Borland语言手册中写:“对象类型存在的目的是为了与旧有但程序兼容,所以并不建议使用它”~~
不过人的想象力是无穷的,就象Kol就是利用对象类型,精简编译出来的代码~~
虽然对象类型确实是早期面向对象使用的类型~~
但对象类型和类类型是不同类型 :)~~
所以你说我错,我可不同意~~
对象类型不需要构造和析构就可以使用,更象是记录类型~~
Borland语言手册中写:“对象类型存在的目的是为了与旧有但程序兼容,所以并不建议使用它”~~
不过人的想象力是无穷的,就象Kol就是利用对象类型,精简编译出来的代码~~
#15
谈论语言间的本质区别应该从编译器实现角度去考虑,毕竟语言是编译器直接处理的对象,语言的一切语法和语意都是和具体编译器实现直接关联的。
语言学习中有一个方面是对象模型,如果楼主注意,可以发现很多语言的对象模型都是非常雷同的,包括现在很流行的基于中间指令的语言,比如Java和C Sharp等等。
对于支持OO的语言无非也是在编译实现和对象模型实现上直接建立内存表格与类或其他语言元素对应以形成支持的,从语言角度来讲,个人认为本质上没有什么大的区别。
楼上有人说继承方面的区别那是区别,但不是本质区别。
语言学习中有一个方面是对象模型,如果楼主注意,可以发现很多语言的对象模型都是非常雷同的,包括现在很流行的基于中间指令的语言,比如Java和C Sharp等等。
对于支持OO的语言无非也是在编译实现和对象模型实现上直接建立内存表格与类或其他语言元素对应以形成支持的,从语言角度来讲,个人认为本质上没有什么大的区别。
楼上有人说继承方面的区别那是区别,但不是本质区别。
#16
我想说的是微软实在太强了
#17
从pascal和c起就有分别了。而且影响了c++和delphi的风格,比较一下vcl和owl。
#18
C++灵活
Delphi简洁
Delphi简洁
#19
什么语言都有,存在就是合理,选择适用好用的,熟手的就是了:)
单根继承也有他的有点的:)新的语言似乎都看中了单根继承的好处:)
我记得Delphi的都是Tobject继承来的,你不声明都是默认TObject的,他是单根的
C#,感觉是Delphi+VC的东西:)
http://lysoft.7u7.net
单根继承也有他的有点的:)新的语言似乎都看中了单根继承的好处:)
我记得Delphi的都是Tobject继承来的,你不声明都是默认TObject的,他是单根的
C#,感觉是Delphi+VC的东西:)
http://lysoft.7u7.net
#20
to zswang
呵呵,和高手讨论就是不一样,本来我认为理所当然的没想到你还可以找到理由反驳!
不过对你的理由,我却不大同意!
想当初C++的类不一样也是带方法的结构,这和OPP的带方法的记录不也是一回事情么?
只不过发展到现在,都把分配对象类存的过程统一到对象构造方法中了!
呵呵,和高手讨论就是不一样,本来我认为理所当然的没想到你还可以找到理由反驳!
不过对你的理由,我却不大同意!
想当初C++的类不一样也是带方法的结构,这和OPP的带方法的记录不也是一回事情么?
只不过发展到现在,都把分配对象类存的过程统一到对象构造方法中了!
#21
只不过发展到现在,都把分配对象,内存的过程统一到对象构造方法中了!
#22
有人在问我:先有鸡还是先有蛋?~~
那么我会反问:
是不是鸡下的蛋都是鸡蛋?
是不是能孵出鸡的蛋都是鸡蛋?
是不是鸡蛋孵出的都是鸡?
是不是能下出鸡蛋的都是鸡?
如果对鸡和蛋的定义本来就是矛盾的,那这个问题则没有答案~~
问题本来是错的,怎么又有正确的答案呢~~
同样我想问zwjchina
class声明出来的叫类
object声明出来的也就类?
那照阁下所说,所有数据的是由0和1组成的,它们本质就没有任何区别~~
所以看来是我错了!~~
那么我会反问:
是不是鸡下的蛋都是鸡蛋?
是不是能孵出鸡的蛋都是鸡蛋?
是不是鸡蛋孵出的都是鸡?
是不是能下出鸡蛋的都是鸡?
如果对鸡和蛋的定义本来就是矛盾的,那这个问题则没有答案~~
问题本来是错的,怎么又有正确的答案呢~~
同样我想问zwjchina
class声明出来的叫类
object声明出来的也就类?
那照阁下所说,所有数据的是由0和1组成的,它们本质就没有任何区别~~
所以看来是我错了!~~
#23
谢谢大家的讨论!
对于“delphi所有的类都必须从TObject继承下来的”这一观点, ly_liuyang(Liu Yang)理解的对,
因为OOP是一种严谨的语言,它对很多在C/C++可以由程序员*发挥的地方做了很多的限制。如果在你的类定义中没有声明它的父类,delphi会默认为TObject类。
这里我还要再次声明一下,提出这个问题,并不是想去比较两种语言孰优孰劣或是该用哪种语言去实现或是用哪一个开发工具。只是想从计算机语言学的角度来比较两种语言的区别和相同的地方。
对于“delphi所有的类都必须从TObject继承下来的”这一观点, ly_liuyang(Liu Yang)理解的对,
因为OOP是一种严谨的语言,它对很多在C/C++可以由程序员*发挥的地方做了很多的限制。如果在你的类定义中没有声明它的父类,delphi会默认为TObject类。
这里我还要再次声明一下,提出这个问题,并不是想去比较两种语言孰优孰劣或是该用哪种语言去实现或是用哪一个开发工具。只是想从计算机语言学的角度来比较两种语言的区别和相同的地方。
#24
听课!!
#25
Object Pascal中的对象单根体系,而C++中无此限制,这是严谨与灵活的区别。
Object Pascal中的对象天生是引用语义,而C++中的对象是值语义。上面有人提到的object类型属于过时的内容,继续保留它只是为了兼容以前的版本,现在完全不用把它看成是Object Pascal中的一个内容,也是由于这个原因,帮助中对这个类型讲得不是很详细,我没有找到为他定义构造、析构以及多态函数的方法(用class类型的方法是不行的)。C++的值对象的一大特点就是自动构造和析构,即使有异常抛出析构也会进行,这样在代码中就减少了try-finally的存在必要;这一特点配合C++的泛型能力更是发展出了RAII技术,使得在C++中异常安全代码的实现更加简化了。比如我在BCB中可以这样写:
{
std::auto_ptr<TForm2> ADlg (new TForm2(NULL));
if (ADlg->ShowModal() == mrOK)
{
...
}
}
而在Delphi中不得不:
var
ADlg: TForm2;
begin
ADlg := TForm2.Create(nil);
try
if ADlg.ShowModal = mrOK then
begin
...
end;
finally
ADlg.Free;
end;
end;
如果一个函数中需要注意释放的资源比较多这种情况更加严重,将会由于多个try-finally嵌套的情况而影响代码可读性。我觉得这一点是Object Pascal的缺点。与C++相比,Object Pascal才是急需引入垃圾回收机制的语言。
Object Pascal中的类没有多继承,但有interface关键字,一个类可以实现多个interface;而C++中则没有interface概念,使用多继承+抽象类来实现这一点,但也可以多继承自普通的类。一般来说,所有目的是重用的继承都可以被组合方式代替,而作为“子类型”的概念,interface概念已经表达得很清楚了,所以这一点上没有多继承并没有什么明显的缺陷。
事实上,在面向对象编程方面,Object Pascal与Java和C#更加接近,不同的是它不是运行在虚拟机中的,也没有垃圾回收机制。
Object Pascal中的对象天生是引用语义,而C++中的对象是值语义。上面有人提到的object类型属于过时的内容,继续保留它只是为了兼容以前的版本,现在完全不用把它看成是Object Pascal中的一个内容,也是由于这个原因,帮助中对这个类型讲得不是很详细,我没有找到为他定义构造、析构以及多态函数的方法(用class类型的方法是不行的)。C++的值对象的一大特点就是自动构造和析构,即使有异常抛出析构也会进行,这样在代码中就减少了try-finally的存在必要;这一特点配合C++的泛型能力更是发展出了RAII技术,使得在C++中异常安全代码的实现更加简化了。比如我在BCB中可以这样写:
{
std::auto_ptr<TForm2> ADlg (new TForm2(NULL));
if (ADlg->ShowModal() == mrOK)
{
...
}
}
而在Delphi中不得不:
var
ADlg: TForm2;
begin
ADlg := TForm2.Create(nil);
try
if ADlg.ShowModal = mrOK then
begin
...
end;
finally
ADlg.Free;
end;
end;
如果一个函数中需要注意释放的资源比较多这种情况更加严重,将会由于多个try-finally嵌套的情况而影响代码可读性。我觉得这一点是Object Pascal的缺点。与C++相比,Object Pascal才是急需引入垃圾回收机制的语言。
Object Pascal中的类没有多继承,但有interface关键字,一个类可以实现多个interface;而C++中则没有interface概念,使用多继承+抽象类来实现这一点,但也可以多继承自普通的类。一般来说,所有目的是重用的继承都可以被组合方式代替,而作为“子类型”的概念,interface概念已经表达得很清楚了,所以这一点上没有多继承并没有什么明显的缺陷。
事实上,在面向对象编程方面,Object Pascal与Java和C#更加接近,不同的是它不是运行在虚拟机中的,也没有垃圾回收机制。
#26
>呵呵,和高手讨论就是不一样,本来我认为理所当然的没想到你还可以找到理由反驳!
>不过对你的理由,我却不大同意!
>想当初C++的类不一样也是带方法的结构,这和OPP的带方法的记录不也是一回事情么?
>只不过发展到现在,都把分配对象类存的过程统一到对象构造方法中了!
这这说法我不能赞同,在C++第一个“标准”——AT&T C++1.0文档中,C++中的类就不只是“带方法的结构”,它支持构造函数的析构函数,最重要的是支持多态。封装、继承与多态是面向对象的三大基本特性,VB一直不被认为是面向对象编程语言的原因正是在于缺乏对继承和多态的支持(VB.Net已经加入了这方面的内容),把“类”仅仅理解为“带方法的结构”不符合面向对象编程的要求。
>不过对你的理由,我却不大同意!
>想当初C++的类不一样也是带方法的结构,这和OPP的带方法的记录不也是一回事情么?
>只不过发展到现在,都把分配对象类存的过程统一到对象构造方法中了!
这这说法我不能赞同,在C++第一个“标准”——AT&T C++1.0文档中,C++中的类就不只是“带方法的结构”,它支持构造函数的析构函数,最重要的是支持多态。封装、继承与多态是面向对象的三大基本特性,VB一直不被认为是面向对象编程语言的原因正是在于缺乏对继承和多态的支持(VB.Net已经加入了这方面的内容),把“类”仅仅理解为“带方法的结构”不符合面向对象编程的要求。
#27
zswang(伴水清清)(专家门诊清洁工)
:Delphi所有的类都必须从TObject继承下来的~~ //这点我不太喜欢哦~~
我就比较喜欢所有的类都从一个基类派生!
:Delphi所有的类都必须从TObject继承下来的~~ //这点我不太喜欢哦~~
我就比较喜欢所有的类都从一个基类派生!
#28
也可以这样写,少用一个变量
with TForm2.Create(nil) do
begin
if ShowModal = mrOK then
begin
...
end;
free;
end;
object 类有的时候还是可以当record一样用一下,不用Create,free
with TForm2.Create(nil) do
begin
if ShowModal = mrOK then
begin
...
end;
free;
end;
object 类有的时候还是可以当record一样用一下,不用Create,free
#29
也可以这样写,少用一个变量
with TForm2.Create(nil) do
begin
try
if ShowModal = mrOK then
begin
...
end;
finally
free;
end;
end;
少了try-finally
不过我不喜欢用with,一旦用了with A do,A的成员就可以直接访问而不用加限定符(我是指那个“A.”)了,如果和以有的不需要限定符的符号(比如Self.XXX)同名就会导致歧义。最头痛的是,当歧义发生时,Object Pascal不告诉你而是替你选择一个,很可能不导致语法错误。在我参与的项目中遇到过好几次问题都是因为使用了一个with,结果找了好久才知道错误在什么地方。
我觉得用object类型当record用没有什么特别的好处,成员函数我完全可以用全局函数代替。
到OO方面的实现细节方面:
我觉得Object Pascal要求显式指明override是很不错的设计,这样避免了由于输入错误导致本想override却成了定义新方法。而在C++仅依靠名字进行判断,如果在衍生类中进行override时输入错了,结果就成了衍生类定义的新方法,编译通过,结果不正确……除非基类中的虚函数都是纯的,子类不override的话不能创建。
Object Pascal的析构函数可以不override,不太合理。在C++中如果基类的析构函数是虚的,衍生类的析构也必然是虚的并且是一个override,因为C++析构函数只能有一个,而OP可以有多个(我一直不明白多个析构函数有什么用)。
C++中构造和析构函数对基类构造和析构函数的调用是强制性的,其中析构函数是自动调用,构造函数中的指定调用,不指定则调用缺省构造,没有缺省构造则编译出错。而OP中构造和析构函数都可以不调用基类中的相关函数,容易出现Bug。
OP中有抽象方法的类也可以创建,只有当某一天代码调用到了这个抽象方法时才会出错;而C++中有未override的纯虚函数的类是不允许实例化的,这一点我更喜欢C++的处理。
非OO方面我最讨厌的是两个问题:
1:OP对指针类型转换的检查太弱了!远没有C++严格——谁说OP一定比C++严谨?
2:C++数组可以隐式转换为指针并且指针可以当数组访问,很另人头痛,不如象OP那样用“指向数组的指针”,不容易出错。
with TForm2.Create(nil) do
begin
try
if ShowModal = mrOK then
begin
...
end;
finally
free;
end;
end;
少了try-finally
不过我不喜欢用with,一旦用了with A do,A的成员就可以直接访问而不用加限定符(我是指那个“A.”)了,如果和以有的不需要限定符的符号(比如Self.XXX)同名就会导致歧义。最头痛的是,当歧义发生时,Object Pascal不告诉你而是替你选择一个,很可能不导致语法错误。在我参与的项目中遇到过好几次问题都是因为使用了一个with,结果找了好久才知道错误在什么地方。
我觉得用object类型当record用没有什么特别的好处,成员函数我完全可以用全局函数代替。
到OO方面的实现细节方面:
我觉得Object Pascal要求显式指明override是很不错的设计,这样避免了由于输入错误导致本想override却成了定义新方法。而在C++仅依靠名字进行判断,如果在衍生类中进行override时输入错了,结果就成了衍生类定义的新方法,编译通过,结果不正确……除非基类中的虚函数都是纯的,子类不override的话不能创建。
Object Pascal的析构函数可以不override,不太合理。在C++中如果基类的析构函数是虚的,衍生类的析构也必然是虚的并且是一个override,因为C++析构函数只能有一个,而OP可以有多个(我一直不明白多个析构函数有什么用)。
C++中构造和析构函数对基类构造和析构函数的调用是强制性的,其中析构函数是自动调用,构造函数中的指定调用,不指定则调用缺省构造,没有缺省构造则编译出错。而OP中构造和析构函数都可以不调用基类中的相关函数,容易出现Bug。
OP中有抽象方法的类也可以创建,只有当某一天代码调用到了这个抽象方法时才会出错;而C++中有未override的纯虚函数的类是不允许实例化的,这一点我更喜欢C++的处理。
非OO方面我最讨厌的是两个问题:
1:OP对指针类型转换的检查太弱了!远没有C++严格——谁说OP一定比C++严谨?
2:C++数组可以隐式转换为指针并且指针可以当数组访问,很另人头痛,不如象OP那样用“指向数组的指针”,不容易出错。
#30
转在网上看到的一篇文章,也许对楼主理解所提出的问题有所帮助
开发工具大比拼之Visual C++ VS Delphi
文:紫云英、曾登高
引言
"Visual C++与Delphi之比较"最近在CSDN的论坛上的讨论非常火热,本文将以一个程序员的角度,从技术水平、功能、性能、易用性、稳定性、发展历程和前景等方面,以Visual C++6和Delphi5为代表,尽可能客观地比较介绍Visual C++和Delphi这两大主流开发工具的优缺点,其中将涉及到语言、应用框架、控件、编译和连接、集成界面、调试、COM、数据库开发等。本文还将对如何选择使用这两个开发工具提出一些建议。
值得一提的是,由于C++Builder与Delphi同为Inprise公司产品,它们除了使用的语言不同,其余特性几乎都相同。因此本文对C++Builder程序员和学习者也有参考价值。
语言:存在即是合理
首先声明常被混淆的一点:VC和Delphi本身不是语言,而是开发平台。它们所用的语言分别是略作扩展的C/C++和Object Pascal。我在网上常看到有人问应该学C/C++还是VC,这个问题很好回答:如果你学VC你就必须得学C/C++,或者说你学会了VC也就学会了C/C++了。
言归正传,我们来比较一下C++和Object Pascal的优缺点。有人认为Object Pascal是"玩具语言",C++才是"专业语言",这是不对的。单从语言本身看,Object Pascal与C++属同一重量级。它们都是完全支持面向对象的语言,都扎根于"历史悠久"的面向过程的语言。C++是由C发展而来的,Object Pascal由Pascal进化而来。它们都有很强的灵活性,都有自己的特长和不足。比如说,Object Pascal不支持多重继承、模板、操作符重载、内联函数定义、预处理、宏、全局静态类变量、嵌套类定义,等等,而这些都是C++支持的。但同样地C++也不支持Object Pascal的虚构造函数、过程嵌套、内置集合类型、内置字符串类型、"finally"构造等等,在RTTI方面Object Pascal也比C++做得好。但这些并不重要,因为可以通过其它方式达到同样的目的,比如C++可以通过类扩展支持集合、字符串,Object Pascal可以通过"interface"多重继承,等等。关键是二者都可以很好地完成你手头的任务,这就够了。
但是,仅仅比较语言本身是不够的,还得看它们的被接受和流行程度,学习曲线,发展前途,可移植性等,以及,很重要但常常被忽略的一点:与开发环境(指VC与Delphi)及其应用框架的"磨合"程度。
VC和Delphi作为开发平台,很重要的一点就是提供了一个"无所不包"的应用框架:VC的MFC和Delphi的VCL。MFC是用C++写的,VCL是用Object Pascal写的。当然,我们都知道,C++的使用范围比Object Pascal广得多,移植性也好得多。这本来是优点,但很有意思的是,正因为如此,微软写MFC时必须考虑最大限度减少对语言本身的改动,而把功夫下在源代码级,以便能尽可能支持ANSI等标准,结果导致MFC的封装复杂而不直观。(尤其是它对消息的封装,下文还会提到)。太多的宏定义和含义模糊且自动生成、不得改动的注释使MFC乃至VC让很多新手望而生畏,不敢"下水"深入学习。而Object Pascal几乎是Inprise"专用"的,不必考虑"标准"问题,因此Inprise写VCL时就把全部精力放在了结构与性能上,结果语言与框架的磨合程度非常好。VCL框架的结构清晰,VCL代码的可读性非常好。许多人说Delphi比较容易上手,也是这个缘故。天下没有白吃的午餐。你要工业标准吗?你要可移植性吗(关于可移植性和兼容性,下文会详细比较)?那么请面对MFC的"天书"级代码吧。
编译和连接:The Need For Speed
不同的语言带来的另一个不同是,编译和连接的速度的不同,以及执行速度的不同。Delphi的编译和连接速度,毫不夸张地说,比VC快几十倍。即使把VC的Incremental Link选项打开,Delphi的编译和连接速度仍比VC快好几倍。并不是说微软的编译器不行,这是由C++的复杂性决定的。模板的处理、预处理和宏的展开都是很费时的。前文不是提到Object Pascal没有模板、预处理和宏吗?这本来是缺点,但带来的一个好处就是编译速度极快。至于编译完的二进制代码,在打开相同的优化选项的情况下,Delphi和VC执行速度并没有太大的差别。
为了克服编译的速度问题,C++编译器一般需要增强的连接器和预处理机制。但是预处理机制仍然存在若干问题:1)程序调试的断点行可能和代码行不同;2)没有将最新的代码信息综合进去;3)容易产生错误的逻辑;4)因为读错文件头而很容易产生类似"Unexpected End of File"的错误。
两个编译器有个共同点是都能识别无用的"死"代码,比如一个没有用的函数等等。编译后的程序将不包含这些多余的信息。Delphi在这方面作得更加出色。它可以让你在编辑器中可视化地提示出那行代码是"活"的、那行代码是"死"的。这样你就能整理出最精简的代码。Delphi在编译后将在左边显示一个小蓝点表示这行代码是"活"的。Visual C++做不到这点。
Delphi编译后可执行文件至少有200K(如果不使用VCL,仅仅使用WinAPI,文件的大小将大大缩小)但是Visual C++编程使用MFC编译后的可执行文件通常只有几十K,主要是因为微软已经将系统运行库包含在Windows系统了(Borland公司曾经和微软协商这个接口,但是微软利用操作系统的优势不愿意公开)。同样道理,使用BDE开发的的数据库程序必须附带3-5M的额外系统文件,也是非常不协调的。
非常有趣的是,Delphi能够使用由C++ Builder创建的的OBJ文件,但是使用上受很大的局限性。
最后,Visual C++的编译和连接时的错误信息比Delphi要详细和具体的多。特别是使用ATL开发更加如此。
应用框架:MFC?有KFC流行吗?
应用程序框架(Application Frame),有时也称为对象框架。Visual C++采用的框架是MFC。MFC不仅仅是人们通常理解的一个类库(同样,Delphi的VCL也不仅仅是一个控件库,尽管它的名字叫"可视控件库")。你如果选择了MFC,也就选择了一种程序结构,一种编程风格。MFC早在Windows 3.x的时代就出现了,那时的Visual C++还是16位的。经过这些年的不断补充和完善,MFC已经十分成熟。但由于原型出现得比较早,MFC相比于VCL落后了一个时代。尽管微软对MFC的更新没有停止,我也经常读到"只要Windows不过时,MFC就不会过时"之类观点的文章,但就象Inprise(原Borland)的OWL框架的淡出一样,MFC的淡出也是早晚的事。其实MFC是和OWL同一个时代的产物。OWL已经不在了,MFC怎能不"居安思危"呢?如果MFC青春永驻,微软的开发人员也不会"私自"开发出基于ATL的WTL呀。当然,WTL的地位不能和MFC比,它并不是微软官方支持的框架,封装的功能也相当有限。但至少也反衬出了MFC存在的不足。
开发工具大比拼之Visual C++ VS Delphi
文:紫云英、曾登高
引言
"Visual C++与Delphi之比较"最近在CSDN的论坛上的讨论非常火热,本文将以一个程序员的角度,从技术水平、功能、性能、易用性、稳定性、发展历程和前景等方面,以Visual C++6和Delphi5为代表,尽可能客观地比较介绍Visual C++和Delphi这两大主流开发工具的优缺点,其中将涉及到语言、应用框架、控件、编译和连接、集成界面、调试、COM、数据库开发等。本文还将对如何选择使用这两个开发工具提出一些建议。
值得一提的是,由于C++Builder与Delphi同为Inprise公司产品,它们除了使用的语言不同,其余特性几乎都相同。因此本文对C++Builder程序员和学习者也有参考价值。
语言:存在即是合理
首先声明常被混淆的一点:VC和Delphi本身不是语言,而是开发平台。它们所用的语言分别是略作扩展的C/C++和Object Pascal。我在网上常看到有人问应该学C/C++还是VC,这个问题很好回答:如果你学VC你就必须得学C/C++,或者说你学会了VC也就学会了C/C++了。
言归正传,我们来比较一下C++和Object Pascal的优缺点。有人认为Object Pascal是"玩具语言",C++才是"专业语言",这是不对的。单从语言本身看,Object Pascal与C++属同一重量级。它们都是完全支持面向对象的语言,都扎根于"历史悠久"的面向过程的语言。C++是由C发展而来的,Object Pascal由Pascal进化而来。它们都有很强的灵活性,都有自己的特长和不足。比如说,Object Pascal不支持多重继承、模板、操作符重载、内联函数定义、预处理、宏、全局静态类变量、嵌套类定义,等等,而这些都是C++支持的。但同样地C++也不支持Object Pascal的虚构造函数、过程嵌套、内置集合类型、内置字符串类型、"finally"构造等等,在RTTI方面Object Pascal也比C++做得好。但这些并不重要,因为可以通过其它方式达到同样的目的,比如C++可以通过类扩展支持集合、字符串,Object Pascal可以通过"interface"多重继承,等等。关键是二者都可以很好地完成你手头的任务,这就够了。
但是,仅仅比较语言本身是不够的,还得看它们的被接受和流行程度,学习曲线,发展前途,可移植性等,以及,很重要但常常被忽略的一点:与开发环境(指VC与Delphi)及其应用框架的"磨合"程度。
VC和Delphi作为开发平台,很重要的一点就是提供了一个"无所不包"的应用框架:VC的MFC和Delphi的VCL。MFC是用C++写的,VCL是用Object Pascal写的。当然,我们都知道,C++的使用范围比Object Pascal广得多,移植性也好得多。这本来是优点,但很有意思的是,正因为如此,微软写MFC时必须考虑最大限度减少对语言本身的改动,而把功夫下在源代码级,以便能尽可能支持ANSI等标准,结果导致MFC的封装复杂而不直观。(尤其是它对消息的封装,下文还会提到)。太多的宏定义和含义模糊且自动生成、不得改动的注释使MFC乃至VC让很多新手望而生畏,不敢"下水"深入学习。而Object Pascal几乎是Inprise"专用"的,不必考虑"标准"问题,因此Inprise写VCL时就把全部精力放在了结构与性能上,结果语言与框架的磨合程度非常好。VCL框架的结构清晰,VCL代码的可读性非常好。许多人说Delphi比较容易上手,也是这个缘故。天下没有白吃的午餐。你要工业标准吗?你要可移植性吗(关于可移植性和兼容性,下文会详细比较)?那么请面对MFC的"天书"级代码吧。
编译和连接:The Need For Speed
不同的语言带来的另一个不同是,编译和连接的速度的不同,以及执行速度的不同。Delphi的编译和连接速度,毫不夸张地说,比VC快几十倍。即使把VC的Incremental Link选项打开,Delphi的编译和连接速度仍比VC快好几倍。并不是说微软的编译器不行,这是由C++的复杂性决定的。模板的处理、预处理和宏的展开都是很费时的。前文不是提到Object Pascal没有模板、预处理和宏吗?这本来是缺点,但带来的一个好处就是编译速度极快。至于编译完的二进制代码,在打开相同的优化选项的情况下,Delphi和VC执行速度并没有太大的差别。
为了克服编译的速度问题,C++编译器一般需要增强的连接器和预处理机制。但是预处理机制仍然存在若干问题:1)程序调试的断点行可能和代码行不同;2)没有将最新的代码信息综合进去;3)容易产生错误的逻辑;4)因为读错文件头而很容易产生类似"Unexpected End of File"的错误。
两个编译器有个共同点是都能识别无用的"死"代码,比如一个没有用的函数等等。编译后的程序将不包含这些多余的信息。Delphi在这方面作得更加出色。它可以让你在编辑器中可视化地提示出那行代码是"活"的、那行代码是"死"的。这样你就能整理出最精简的代码。Delphi在编译后将在左边显示一个小蓝点表示这行代码是"活"的。Visual C++做不到这点。
Delphi编译后可执行文件至少有200K(如果不使用VCL,仅仅使用WinAPI,文件的大小将大大缩小)但是Visual C++编程使用MFC编译后的可执行文件通常只有几十K,主要是因为微软已经将系统运行库包含在Windows系统了(Borland公司曾经和微软协商这个接口,但是微软利用操作系统的优势不愿意公开)。同样道理,使用BDE开发的的数据库程序必须附带3-5M的额外系统文件,也是非常不协调的。
非常有趣的是,Delphi能够使用由C++ Builder创建的的OBJ文件,但是使用上受很大的局限性。
最后,Visual C++的编译和连接时的错误信息比Delphi要详细和具体的多。特别是使用ATL开发更加如此。
应用框架:MFC?有KFC流行吗?
应用程序框架(Application Frame),有时也称为对象框架。Visual C++采用的框架是MFC。MFC不仅仅是人们通常理解的一个类库(同样,Delphi的VCL也不仅仅是一个控件库,尽管它的名字叫"可视控件库")。你如果选择了MFC,也就选择了一种程序结构,一种编程风格。MFC早在Windows 3.x的时代就出现了,那时的Visual C++还是16位的。经过这些年的不断补充和完善,MFC已经十分成熟。但由于原型出现得比较早,MFC相比于VCL落后了一个时代。尽管微软对MFC的更新没有停止,我也经常读到"只要Windows不过时,MFC就不会过时"之类观点的文章,但就象Inprise(原Borland)的OWL框架的淡出一样,MFC的淡出也是早晚的事。其实MFC是和OWL同一个时代的产物。OWL已经不在了,MFC怎能不"居安思危"呢?如果MFC青春永驻,微软的开发人员也不会"私自"开发出基于ATL的WTL呀。当然,WTL的地位不能和MFC比,它并不是微软官方支持的框架,封装的功能也相当有限。但至少也反衬出了MFC存在的不足。
#31
..接上
我们以为,最能体现一个应用程序框架的先进性的是它的委托模型,即对Windows消息的封装机制。对Windows API的封装就不用说了吧。大同小异,也没什么技术含量。如果高兴,你也可以自己写一个类库来封装。但对Windows消息驱动机制的封装就不是那么容易的了。最自然的封装方式是采用虚成员函数。如果要响应某个消息就重载相应的虚函数。但出乎我的意料,MFC采用的是"古老"的宏定义方法。用宏定义方法的好处是省去了虚函数VTable的系统开销(由于Windows的消息种类很多,开销不算太小)。不过带来的缺点就是映射不太直观。对于MFC,则是"太不直观"了。它的消息映射代码虽然是可见的,但"劝君莫碰"。好在VC的ClassWizard可以自动生成消息映射代码,使用起来还算方便。但和VCL的委托模型相比,MFC的映射方法就显得太落后了。而Delphi的Object Pascal因为没有"标准负担",语言引入了组件、事件处理、属性等新特性。由于功夫做在编译器级,生成的源代码就显得十分简洁。似乎VC是"让框架迁就语言",而Delphi是"让语言迁就框架"。
我想举一个对字符串操作的封装的例子来说明MFC和VCL的优缺点。在MFC中,CStringList类有加入、获取、删除等功能,但VCL的TStringList类除了上述功能还有排序、从逗号分隔的字串读入、流输入输出等功能。但同样的字符串替换功能,VCL的StringReplace要比MFC的CString::Replace慢2-3倍。总的来说,VCL的封装比MFC更为高层,更为抽象,但不可避免地带来的问题是某些部分执行效率比MFC略低。这就象低级语言(如汇编)的执行效率比高级语言(如Basic)高,但编程效率较低。鱼和熊掌不可兼得嘛。
VCL比之MFC的另一优点是对异常处理的支持,而一大缺点是对多线程支持差。VCL的大部分都不是针对多线程优化的。虽说VCL提供了简化多线程操作的类,但只是工作者线程(worker threads)使用起来比较简单。如果线程要和界面打交道的话事情就变得麻烦了,因为除了应用程序的主线程,任何线程不能访问任何可视的VCL部件。你不得不使用Synchronize方法等待主线程处理它的消息,然后在主线程中访问VCL部件。而MFC就没有这样的限制。
稳定性与完善程度:VC是老大哥
VC要比Delphi稳定和完善。VC的发展历史比Delphi长,微软的总体实力比Inprise强。VC的框架MFC经历了那么多年的发展和完善,功能非常全面,而且十分稳定,bug很少。其中你可能遇到的bug也更少。而且有第三方的专门工具帮助你避开这些bug。如此规模的一个类库,能做到这一点不容易。不要小看了这一点,很多专业程序员就是为这个选择VC的。因为尽管VCL比MFC的抽象程度高,封装较为高层,但由此带来的开发效率的提高对高手来说毕竟是有限的。而如果你遇到一个怪问题,调试了半天,发现不是你的代码有错,而是VCL的bug,你作何感想?虽说遇到这类问题的可能性很小,但对VCL的形象的影响可不小。Delphi的IDE太占资源,启动速度太慢,和某些显卡驱动程序冲突,VCL中有bug,调试器不够健壮,对不稳定的第三方控件没有防护措施 …… 问题多多,在这方面Delphi不如VC。希望Inprise能更上一层楼。顺便说一下,我们在网上看到有些人极言Delphi的不稳定,说几分钟出现20多次非法操作。Delphi的确不如Visual C++稳定,但也不至于如此呀。我估计是那位朋友的Delphi装了某些有问题的第三方控件,导致了Delphi的频频出错。不妨卸下那些控件试试?
可移植性:立足现实,放眼未来
Inprise正在开发Delphi的Linux版本,代号为Kylix。也许通过Kylix,用VCL构架编写的Windows程序向Linux移植成为可能。但这只是可能。因为在目前Inprise的兼容性工作做得并不好。低版本的Delphi不能使用高版本的VCL组件,而高版本的Delphi竟然不能使用低版本的VCL组件。真是岂有此理,我们很少看见软件有不向下二进制兼容的。如果Windows 98不能运行95的程序,Windows 95不能运行3.x的程序,Win 3.x不能运行DOS程序,你还会用Windows吗?如果Windows 95的程序必须经过重新编译才能在98下运行,98会卖得那么好吗?"同门兄弟"C++Builder和Delphi也不能互相使用对方的组件,甚至同一套VCL库的文件名也不一样。所以一个组件有for D1/D2/D3/D4/D5/C1/C3/C4/C5这些不同版本是常有的事,而且随着Delphi和C++Builder版本的升级可能还会增加。希望Inprise能先解决同门兄弟的兼容性问题。而微软的VC就没有这类问题。MFC1.0的程序也可以毫无障碍地在VC6.0下编译通过。
集成界面:宏观与微观
就大处说,VC的集成界面是不如Delphi的。Delphi仅仅一个Object Inspector就可以将VC的一堆Wizards比下去,何况它还有Code Explorer、ToDo List等。但从小处,又可以看出Delphi的不成熟。比如"自动完成"功能的智能化程度和提示详细程度不如VC,响应速度也没有VC快。
Visual C++所带的MSDN是一部"开发者的百科全书",信息庞大,查询方便,这方面比Delphi更专业。很多帮助项都有源程序示范。
Delphi的OpenTools是完全面向第三方的开放系统,开发者可以修改很多Borland公司自身的功能,从IDE的可扩充性上说Delphi更好。
调试:细微之处见真功
Visual C++和Delphi的调试功能都非常强大,同时都具有单步可视化调试、断点跟踪、运行时改变变量、鼠标指向可以得到变量值等等功能。对DLL的输入输出也能方便的管理,能够进行源码级别的调试。
相对而言,Visual C++能够更加方便地看到变量的变化情况,这包括对结构可以展开成数据树,从而了解每一个变量的值,每一步调试,变化了的变量会加红,从而使调试更加方便。另外,Visual C++的块内存察看比Delphi也要方便。
当然,Delphi也有很多体贴的细微之处,比如在线程调试的时候,Delphi能够很方便地察看线程的变化,Visual C++却必须要弹出一个模式对话框。
我们以为,最能体现一个应用程序框架的先进性的是它的委托模型,即对Windows消息的封装机制。对Windows API的封装就不用说了吧。大同小异,也没什么技术含量。如果高兴,你也可以自己写一个类库来封装。但对Windows消息驱动机制的封装就不是那么容易的了。最自然的封装方式是采用虚成员函数。如果要响应某个消息就重载相应的虚函数。但出乎我的意料,MFC采用的是"古老"的宏定义方法。用宏定义方法的好处是省去了虚函数VTable的系统开销(由于Windows的消息种类很多,开销不算太小)。不过带来的缺点就是映射不太直观。对于MFC,则是"太不直观"了。它的消息映射代码虽然是可见的,但"劝君莫碰"。好在VC的ClassWizard可以自动生成消息映射代码,使用起来还算方便。但和VCL的委托模型相比,MFC的映射方法就显得太落后了。而Delphi的Object Pascal因为没有"标准负担",语言引入了组件、事件处理、属性等新特性。由于功夫做在编译器级,生成的源代码就显得十分简洁。似乎VC是"让框架迁就语言",而Delphi是"让语言迁就框架"。
我想举一个对字符串操作的封装的例子来说明MFC和VCL的优缺点。在MFC中,CStringList类有加入、获取、删除等功能,但VCL的TStringList类除了上述功能还有排序、从逗号分隔的字串读入、流输入输出等功能。但同样的字符串替换功能,VCL的StringReplace要比MFC的CString::Replace慢2-3倍。总的来说,VCL的封装比MFC更为高层,更为抽象,但不可避免地带来的问题是某些部分执行效率比MFC略低。这就象低级语言(如汇编)的执行效率比高级语言(如Basic)高,但编程效率较低。鱼和熊掌不可兼得嘛。
VCL比之MFC的另一优点是对异常处理的支持,而一大缺点是对多线程支持差。VCL的大部分都不是针对多线程优化的。虽说VCL提供了简化多线程操作的类,但只是工作者线程(worker threads)使用起来比较简单。如果线程要和界面打交道的话事情就变得麻烦了,因为除了应用程序的主线程,任何线程不能访问任何可视的VCL部件。你不得不使用Synchronize方法等待主线程处理它的消息,然后在主线程中访问VCL部件。而MFC就没有这样的限制。
稳定性与完善程度:VC是老大哥
VC要比Delphi稳定和完善。VC的发展历史比Delphi长,微软的总体实力比Inprise强。VC的框架MFC经历了那么多年的发展和完善,功能非常全面,而且十分稳定,bug很少。其中你可能遇到的bug也更少。而且有第三方的专门工具帮助你避开这些bug。如此规模的一个类库,能做到这一点不容易。不要小看了这一点,很多专业程序员就是为这个选择VC的。因为尽管VCL比MFC的抽象程度高,封装较为高层,但由此带来的开发效率的提高对高手来说毕竟是有限的。而如果你遇到一个怪问题,调试了半天,发现不是你的代码有错,而是VCL的bug,你作何感想?虽说遇到这类问题的可能性很小,但对VCL的形象的影响可不小。Delphi的IDE太占资源,启动速度太慢,和某些显卡驱动程序冲突,VCL中有bug,调试器不够健壮,对不稳定的第三方控件没有防护措施 …… 问题多多,在这方面Delphi不如VC。希望Inprise能更上一层楼。顺便说一下,我们在网上看到有些人极言Delphi的不稳定,说几分钟出现20多次非法操作。Delphi的确不如Visual C++稳定,但也不至于如此呀。我估计是那位朋友的Delphi装了某些有问题的第三方控件,导致了Delphi的频频出错。不妨卸下那些控件试试?
可移植性:立足现实,放眼未来
Inprise正在开发Delphi的Linux版本,代号为Kylix。也许通过Kylix,用VCL构架编写的Windows程序向Linux移植成为可能。但这只是可能。因为在目前Inprise的兼容性工作做得并不好。低版本的Delphi不能使用高版本的VCL组件,而高版本的Delphi竟然不能使用低版本的VCL组件。真是岂有此理,我们很少看见软件有不向下二进制兼容的。如果Windows 98不能运行95的程序,Windows 95不能运行3.x的程序,Win 3.x不能运行DOS程序,你还会用Windows吗?如果Windows 95的程序必须经过重新编译才能在98下运行,98会卖得那么好吗?"同门兄弟"C++Builder和Delphi也不能互相使用对方的组件,甚至同一套VCL库的文件名也不一样。所以一个组件有for D1/D2/D3/D4/D5/C1/C3/C4/C5这些不同版本是常有的事,而且随着Delphi和C++Builder版本的升级可能还会增加。希望Inprise能先解决同门兄弟的兼容性问题。而微软的VC就没有这类问题。MFC1.0的程序也可以毫无障碍地在VC6.0下编译通过。
集成界面:宏观与微观
就大处说,VC的集成界面是不如Delphi的。Delphi仅仅一个Object Inspector就可以将VC的一堆Wizards比下去,何况它还有Code Explorer、ToDo List等。但从小处,又可以看出Delphi的不成熟。比如"自动完成"功能的智能化程度和提示详细程度不如VC,响应速度也没有VC快。
Visual C++所带的MSDN是一部"开发者的百科全书",信息庞大,查询方便,这方面比Delphi更专业。很多帮助项都有源程序示范。
Delphi的OpenTools是完全面向第三方的开放系统,开发者可以修改很多Borland公司自身的功能,从IDE的可扩充性上说Delphi更好。
调试:细微之处见真功
Visual C++和Delphi的调试功能都非常强大,同时都具有单步可视化调试、断点跟踪、运行时改变变量、鼠标指向可以得到变量值等等功能。对DLL的输入输出也能方便的管理,能够进行源码级别的调试。
相对而言,Visual C++能够更加方便地看到变量的变化情况,这包括对结构可以展开成数据树,从而了解每一个变量的值,每一步调试,变化了的变量会加红,从而使调试更加方便。另外,Visual C++的块内存察看比Delphi也要方便。
当然,Delphi也有很多体贴的细微之处,比如在线程调试的时候,Delphi能够很方便地察看线程的变化,Visual C++却必须要弹出一个模式对话框。
#32
..接上
数据库开发:Delphi一枝独秀
数据库支持是Delphi的强项。这主要体现在Delphi与BDE的无缝集成,以及Delphi提供的那一大堆现成的数据库操作控件。这是VC望尘莫及的。目前Delphi支持BDE、ADO、InterBase三种数据库访问方式。所有的方式都能拖拉到应用程序中实现可视化操作。正是因为Delphi对数据库类的包装,使得用户操作数据库不像在Visual C++中必须从开始到最后都要干预。明显地提高了开发速度。
Delphi中使用WebBroker控件还能很方便地构造出基于数据库的Web页面,通过HTML管理Web数据库。 Visual C++访问数据主要通过ADO和OLEDB,很多ActiveX控件也能添加数据库功能。但是没有像Paradox这样的桌面数据库,Access相对功能太弱了。也许SQL Server是不错的选择。
COM:新技术的力量
COM是组件对象模型的缩写。它是OLE和ActiveX技术的基础,COM定义了一组API和一个二进制标准,让不同的编程语言、不同平台的彼此独立的对象相互进行通讯。
COM是Microsoft制订的行业标准。但Delphi也为COM提供了强大的语言支持。支持接口、variant、宽字符串功能。这些对COM的封装确实比C++更方便。比如在C++(没有类框架)进行COM编程时,变体定义为oaidl.h文件中的VARIANT结构。要处理变体,必须手工调整oleaut32.dll中VariantXXXX() API函数对其进行初始化和管理,如VariantInit()、VariantCopy()、VariantClear()等等。
Visual C++实现COM编程有一种特殊的方法就是使用ATL。ATL使用Visual C++特有的多重继承来实现COM接口。虽然不见得实现COM服务和控制更容易,但是ATL和最新COM技术的接口,基于模板的构造都比Delphi强。ATL更有利于建立小巧、快捷的COM组件程序。
按目前通用的观点,Visual C++应用到COM服务程序更有优势,Delphi应用到COM组件程序更合适。
昨天,今天,明天
技术的进步在很多时候是此消彼长的。当初Borland的Turbo C和Borland C++几乎是C/C++程序员唯一的选择。微软的Quick C(现在还有人知道这个产品吗?)和Microsoft C/C++从来也没有成为过主流。但Borland C++又流行了多少年呢?不久就被新崛起的Microsoft Visual C/C++压下去了。于是Inprise(原Borland)拣起了当年Turbo Pascal和Borland Pascal的辉煌(事实上Borland的成名作就是第一个Pascal编译器),全力推出了Delphi。Delphi当初推出时被称为VB杀手,但VB现在仍然活得挺好。毕竟微软是靠Basic起家的嘛,VB不是那么容易被打败的。Inprise想了想不和VB争了,使用Delphi的IDE和VCL配上C++语言,推出了C++Builder,又向Visual C++的市场发起了夹攻。C++Builder似乎是个不错的折衷选择了?再仔细想想!C++Builder的优点Delphi都有,但Delphi的优点C++Builder未必有。比如C++Builder的编译速度比VC还慢,哪能和Delphi比?而且因为VCL是Object Pascal写的,C++语言和VCL磨合得并不好。C++Builder的bug比Delphi还多,甚至Sample代码中还有错。VCL的部分功能不能使用,要靠嵌入pascal代码访问。C++Builder可用的第三方控件远没有Delphi多。
唉,真是金无足赤。Microsoft和Inprise,谁会笑在最后呢?
鱼和熊掌:艰难的选择
选择一个开发工具依赖于很多不同的因素,每个人都能因为某种语言的某个缺陷而放弃学习或使用这种语言。任何程序员都希望自己喜欢的工具能达到理想的境界,通过上面不完善的比较,我想大家都有自己的看法。我们认为影响大家选择开发语言的因素主要包括:
1) 哪门语言更容易入门?
学习一种语言需要投入大量的时间和精力。开发程序的开发成本是值得考虑的现实。一个熟练的Delphi程序员和一个熟练的VC程序员工作效率是一样的。但是,成为熟练的程序员必须很快掌握一门语言的技巧。不幸的是,目前熟练的Visual C++程序员是十里挑一。相对而言,Delphi更适合初学者。
2) 哪门语言有更多可继承的代码?
语言代码的可重用性是加快开发效率明显方面,从早期的过程、函数到现在的组件技术都是朝这个目标在奋斗。这两种语言对代码重用的理解是不一样的,Delphi主要通过VCL控件来实现代码重用,Visual C++实现起来就比较复杂。
3) 语言自身的本性。
就技术(主要指应用框架)来说,Delphi目前领先于Visual C++。但稳定性和健壮性的不足又让我对Inprise"想说爱你不容易"。而VC尽管发展到今日已十分完善,但MFC框架已是明日黄花了。如果不使用MFC,目前又没有合适的替代品。根据你的需要和实际情况做选择吧。实际上Visual C++和Delphi也不是简单竞争关系。它们在许多领域并不重叠,甚至是互补的。到底怎样取舍,要根据你的项目特性决定。如果你开发系统底层的东西,需要极好的兼容性和稳定性,选Visual C++吧。你可以只调用Windows的各种API,不用MFC。如果你写传统的Windows桌面应用程序,Visual C++的MFC框架是"正统"的选择;如果界面部分占这个应用程序代码比例较大的话,或者Delphi中有相关功能的控件的话,Delphi是事半功倍的选择。如果你为企业开发数据库、信息管理系统等高层应用("高层"是相对于"低层/底层"而言的,不是说技术高级或低级),而且有比较紧的期限限制,选Delphi比较好。如果你熟悉的语言是Object Pascal,又不打算学复杂的C++,那么Delphi几乎是唯一的选择。传统的观点是:Delphi适合编写Internet/Intranet、表格制图、数据库操作、高级用户界面等等。Visual C++适合编写设备驱动、COM服务程序、科学计算、控制台(console)程序、WinCE的应用和一些小的工具等等。应用范围的不同要求好的程序员同时精通这两门语言。
4) 语言的前景和可扩充性。
Delphi是Inprise的旗舰产品之一,前景应当还是比较乐观的,而且Inprise已经在向Linux进军了,而微软还迟迟没有动作。遗憾的是,Inprise公司Delphi的创始人已经跳槽到微软去主持Visual J++和C#项目了。但愿对Inprise冲击不会太大。
微软的Visual C++的前景又怎样呢?Visual Studio 7.0就要推出了。这一版本将加强网络开发的特性。看来微软虽然被判解体,开发实力可是一点没打折扣。
另外,虽说MFC已稍显落后,但不是说它不值得学。事实上,不学MFC就等于没学VC。利用MFC框架开发程序仍然是目前开发桌面应用的主流模式,而且还会保持相当长的时间。微软公司CEO史蒂夫·巴尔默(Steve Ballmer)曾说,.NET流行还得等2-3年。那么,MFC至少还有2-3年的生命空间。在技术日新月异的IT界,2-3年实在是很长一段时间了。好好把握吧。即使你不使用MFC框架,花点时间看一下MFC的封装机制对你熟悉C++的OOP机制和Windows底层功能也是很有好处的。而VCL的源代码是Object Pascal的,对C/C++程序员就没有这个"额外"的作用了。
参考文献:
Programming Microsoft Visual C++, 5th Edition, by Scot Wingo & George Shepherd
MSDN, by Microsoft Corp.
Visual C++ versus Delphi, by John M. Jacobson BorlandC++Builder3Unleashed,byCharlieCalvert,etal.
Borland Delphi 5-Developer's Guide,by Inprise Corp.
<<完>>
数据库开发:Delphi一枝独秀
数据库支持是Delphi的强项。这主要体现在Delphi与BDE的无缝集成,以及Delphi提供的那一大堆现成的数据库操作控件。这是VC望尘莫及的。目前Delphi支持BDE、ADO、InterBase三种数据库访问方式。所有的方式都能拖拉到应用程序中实现可视化操作。正是因为Delphi对数据库类的包装,使得用户操作数据库不像在Visual C++中必须从开始到最后都要干预。明显地提高了开发速度。
Delphi中使用WebBroker控件还能很方便地构造出基于数据库的Web页面,通过HTML管理Web数据库。 Visual C++访问数据主要通过ADO和OLEDB,很多ActiveX控件也能添加数据库功能。但是没有像Paradox这样的桌面数据库,Access相对功能太弱了。也许SQL Server是不错的选择。
COM:新技术的力量
COM是组件对象模型的缩写。它是OLE和ActiveX技术的基础,COM定义了一组API和一个二进制标准,让不同的编程语言、不同平台的彼此独立的对象相互进行通讯。
COM是Microsoft制订的行业标准。但Delphi也为COM提供了强大的语言支持。支持接口、variant、宽字符串功能。这些对COM的封装确实比C++更方便。比如在C++(没有类框架)进行COM编程时,变体定义为oaidl.h文件中的VARIANT结构。要处理变体,必须手工调整oleaut32.dll中VariantXXXX() API函数对其进行初始化和管理,如VariantInit()、VariantCopy()、VariantClear()等等。
Visual C++实现COM编程有一种特殊的方法就是使用ATL。ATL使用Visual C++特有的多重继承来实现COM接口。虽然不见得实现COM服务和控制更容易,但是ATL和最新COM技术的接口,基于模板的构造都比Delphi强。ATL更有利于建立小巧、快捷的COM组件程序。
按目前通用的观点,Visual C++应用到COM服务程序更有优势,Delphi应用到COM组件程序更合适。
昨天,今天,明天
技术的进步在很多时候是此消彼长的。当初Borland的Turbo C和Borland C++几乎是C/C++程序员唯一的选择。微软的Quick C(现在还有人知道这个产品吗?)和Microsoft C/C++从来也没有成为过主流。但Borland C++又流行了多少年呢?不久就被新崛起的Microsoft Visual C/C++压下去了。于是Inprise(原Borland)拣起了当年Turbo Pascal和Borland Pascal的辉煌(事实上Borland的成名作就是第一个Pascal编译器),全力推出了Delphi。Delphi当初推出时被称为VB杀手,但VB现在仍然活得挺好。毕竟微软是靠Basic起家的嘛,VB不是那么容易被打败的。Inprise想了想不和VB争了,使用Delphi的IDE和VCL配上C++语言,推出了C++Builder,又向Visual C++的市场发起了夹攻。C++Builder似乎是个不错的折衷选择了?再仔细想想!C++Builder的优点Delphi都有,但Delphi的优点C++Builder未必有。比如C++Builder的编译速度比VC还慢,哪能和Delphi比?而且因为VCL是Object Pascal写的,C++语言和VCL磨合得并不好。C++Builder的bug比Delphi还多,甚至Sample代码中还有错。VCL的部分功能不能使用,要靠嵌入pascal代码访问。C++Builder可用的第三方控件远没有Delphi多。
唉,真是金无足赤。Microsoft和Inprise,谁会笑在最后呢?
鱼和熊掌:艰难的选择
选择一个开发工具依赖于很多不同的因素,每个人都能因为某种语言的某个缺陷而放弃学习或使用这种语言。任何程序员都希望自己喜欢的工具能达到理想的境界,通过上面不完善的比较,我想大家都有自己的看法。我们认为影响大家选择开发语言的因素主要包括:
1) 哪门语言更容易入门?
学习一种语言需要投入大量的时间和精力。开发程序的开发成本是值得考虑的现实。一个熟练的Delphi程序员和一个熟练的VC程序员工作效率是一样的。但是,成为熟练的程序员必须很快掌握一门语言的技巧。不幸的是,目前熟练的Visual C++程序员是十里挑一。相对而言,Delphi更适合初学者。
2) 哪门语言有更多可继承的代码?
语言代码的可重用性是加快开发效率明显方面,从早期的过程、函数到现在的组件技术都是朝这个目标在奋斗。这两种语言对代码重用的理解是不一样的,Delphi主要通过VCL控件来实现代码重用,Visual C++实现起来就比较复杂。
3) 语言自身的本性。
就技术(主要指应用框架)来说,Delphi目前领先于Visual C++。但稳定性和健壮性的不足又让我对Inprise"想说爱你不容易"。而VC尽管发展到今日已十分完善,但MFC框架已是明日黄花了。如果不使用MFC,目前又没有合适的替代品。根据你的需要和实际情况做选择吧。实际上Visual C++和Delphi也不是简单竞争关系。它们在许多领域并不重叠,甚至是互补的。到底怎样取舍,要根据你的项目特性决定。如果你开发系统底层的东西,需要极好的兼容性和稳定性,选Visual C++吧。你可以只调用Windows的各种API,不用MFC。如果你写传统的Windows桌面应用程序,Visual C++的MFC框架是"正统"的选择;如果界面部分占这个应用程序代码比例较大的话,或者Delphi中有相关功能的控件的话,Delphi是事半功倍的选择。如果你为企业开发数据库、信息管理系统等高层应用("高层"是相对于"低层/底层"而言的,不是说技术高级或低级),而且有比较紧的期限限制,选Delphi比较好。如果你熟悉的语言是Object Pascal,又不打算学复杂的C++,那么Delphi几乎是唯一的选择。传统的观点是:Delphi适合编写Internet/Intranet、表格制图、数据库操作、高级用户界面等等。Visual C++适合编写设备驱动、COM服务程序、科学计算、控制台(console)程序、WinCE的应用和一些小的工具等等。应用范围的不同要求好的程序员同时精通这两门语言。
4) 语言的前景和可扩充性。
Delphi是Inprise的旗舰产品之一,前景应当还是比较乐观的,而且Inprise已经在向Linux进军了,而微软还迟迟没有动作。遗憾的是,Inprise公司Delphi的创始人已经跳槽到微软去主持Visual J++和C#项目了。但愿对Inprise冲击不会太大。
微软的Visual C++的前景又怎样呢?Visual Studio 7.0就要推出了。这一版本将加强网络开发的特性。看来微软虽然被判解体,开发实力可是一点没打折扣。
另外,虽说MFC已稍显落后,但不是说它不值得学。事实上,不学MFC就等于没学VC。利用MFC框架开发程序仍然是目前开发桌面应用的主流模式,而且还会保持相当长的时间。微软公司CEO史蒂夫·巴尔默(Steve Ballmer)曾说,.NET流行还得等2-3年。那么,MFC至少还有2-3年的生命空间。在技术日新月异的IT界,2-3年实在是很长一段时间了。好好把握吧。即使你不使用MFC框架,花点时间看一下MFC的封装机制对你熟悉C++的OOP机制和Windows底层功能也是很有好处的。而VCL的源代码是Object Pascal的,对C/C++程序员就没有这个"额外"的作用了。
参考文献:
Programming Microsoft Visual C++, 5th Edition, by Scot Wingo & George Shepherd
MSDN, by Microsoft Corp.
Visual C++ versus Delphi, by John M. Jacobson BorlandC++Builder3Unleashed,byCharlieCalvert,etal.
Borland Delphi 5-Developer's Guide,by Inprise Corp.
<<完>>
#33
这篇文章看内容应该很老,不过我没有看过,有些地方不太同意,在这里列出来供大家参考:
>……但VCL的TStringList类除了上述功能还有排序、从逗号分隔的字串读入、流输入输出等功
>能。……
CStringList实现了迭代器模式,这是一种算法与数据结构相分离的模式,当然不会再把排序等算法放到容器中。事实上我如果为它写一个简单的适配器就可以使用stl中的所有算法,包括排序、二分查找、并配合i(o)stream_iterator实现流输入输出,还可以使用很多其它算法TStringList中没有的其它算法。字符串分割的算法stl中没有,但如果你写了一个,它将不只可以用于CStringList,还可以用于std::vector<std::string>,std::vector<CString>,std::list<std::string>,std::list<CString>……这是一种成熟的模式而不是缺陷。反观VCL,TStringList中有一个Sort,TList中也有一个Sort,但如果我要对一个TCollection中的元素进行排序呢?好象都用不上。如果某一天我写了一个新的容器,还要自已为它实现一个Sort……
>Delphi的OpenTools是完全面向第三方的开放系统,开发者可以修改很多Borland公司自身的功能,
>从IDE的可扩充性上说Delphi更好。
我个人比较喜欢Delphi/BCB的IDE,但关于可扩充性上我要为VC说一句公道话。虽然Delphi/BCB的OpenTools灵活强大,几乎什么都可以做(包括写一个病毒),但使用起来不是很容易;而VC中的宏相比之下很简单好用,很多在VC中很容易写的宏在Delphi中要写一大段代码来实现,而这些扩充其实是很常见的。一个功能强大,一个简单好用,两个相比不能说谁强过了谁。如果把两种方法结合起来——简单的事情由宏实现,复杂的问题写复杂的代码——这样会用起来更方便。
>即使你不使用MFC框架,花点时间看一下MFC的封装机制对你熟悉C++的OOP机制和Windows底层功能也
>是很有好处的。
熟悉Windows底层是有的,但MFC并不代表C++的OOP机制。事实上,在GUI方面,MFC可以说只是对Windows API的最简单的封装,几乎每一个方法都可以在Windows API中找到对应版本——只是少了个Handle参数,并且到处都能看到Windows消息出现。MFC中比较值得一提的是内置的文档—视图模式(MVC模式的一个变种)和对永久化的支持,不过文档—视图模式在遇到不需要这种模式的应用时反而增加了复杂度,在VC5中这一点尤其明显,不过在VC6中这一模式成为可选项了。VC中的永久化初上手用的时候很方便,但更多时候我们需要严格控制文件格式,这时它的帮助就不大的;并且它的实现还忽略了一个永久化时应该处理的重要问题——字节序问题。
事实上MFC应该说是一个成功的Windows下的GUI框架,但不能说它是一个优秀的框架,与QT或是wxWindows相比差得很远,即使是MS的工程师也承认:“MFC其实是一个失败的作品。”但由于各种原因(比较兼容旧版本),MFC很难作出什么改动。MS恐怕也没有想过再对它进行改动,在多年前就已经开始酝酿.Net了,最终目标就是让大家转到.Net框架上,这样对MFC动大手术就成了没有必要的举动。
>C++Builder似乎是个不错的折衷选择了?再仔细想想!C++Builder的优点Delphi都有,但Delphi的
>优点C++Builder未必有。比如C++Builder的编译速度比VC还慢,哪能和Delphi比?
我可不这样想,BCB一直是我比较喜欢的开发工具,如果它的编译优化实现得再好一些就是我最喜欢的了。与用Delphi相比,BCB并非是有破坏无建设,在BCB中,我可以使用STL容器和算法(VCL在这方面做得还不够),还可以使用boost、loki等第三方库的能力,并把这些都和VCL对象结合在一起使用,非常方便。我可以使用RAII来处理异常,用scoped_lock来加锁和解锁,不用再在代码中写丑陋的try-finally。可能最大的缺点就是没有message handler方法,不得不用多分支语句来完成Windows消息的分派(不要去看那些丑陋的宏,其实就是switch、case、default)——和MFC学的,不过这些只是在你需要自己处理Windows消息时才用到,由于VCL的优秀封装,这种情况并不常见。
>COM是Microsoft制订的行业标准。但Delphi也为COM提供了强大的语言支持。支持接口、variant、
>宽字符串功能。这些对COM的封装确实比C++更方便。
C/C++最重要的思想就是“语言没有能力,由库来实现”,不使用框架如果是指不使用任何程序库的话,那你还能用C/C++做什么?Delphi中内置支持确实不错,但我在VC中用_com_ptr_t、variant_t、bstr_t也并没有感到不方便。注意这些类并不是ATL或是MFC的内容,它们是独立存在的。在这里C++体现了它强大的类型扩充能力,有什么不满意的还可以再扩充。而Object Pascal由于没有这种能力(需要值对象+自定义操作符+模板),只能由语言支持,但支持得不好的情况你也只能忍受。在D6中在Variant中存放无符号整数有问题:它用_VarToInt来转换到无符号整数,虽然D5中也是这样做的,但D6中这个单元加进了整数溢出检查,结果只能有一半的无符号整数放到Variant中并成功取出来。WordBool放到Variant也有问题:当内容是true时,它会转换为bool的true,然后这个值会直接返回,这是一个整数1,而WordBool的逻辑是true是-1,结果判断为假。这两个问题都是我在项目中遇到的。还有前一段时间遇到主要时间花费在OleVaraint的释放上——1w个左右要180秒,我改用内部类型存储后只要1xx毫秒,不知道是COM的问题还是Object Pascal的问题。
还有无观紧要的一点:Borland的成名作应该是SK而不是Turbo Pascal,SK在Turbo Pascal之前就取得了成功,它的用户远比Turbo Pascal的用户多——尽管它是防拷贝的而Turbo Pascal没有。记得当年学习汇编时我就是用SK进行源代码编辑(当然,是D版的)。Turbo Pascal是一个里程碑式的产品,但它对Borland的重要性远比不上它对Pascal的重要性。Turbo C的成功才是Borland的开发工具上的里程碑,而这一成功其实是Turbo Debuger带来的——尽管TC的“一次扫描编译”听上去很让人激动。后来到了BC系列,Borland的IDE和工具才真正体现出优点来,尤其是Resouse WorkShop,它的出现让程序员不再需要在坐标纸上描对话框,可以说是最早的成功的“可视化编程”概念——RC文件也是程序,不是吗?
>……但VCL的TStringList类除了上述功能还有排序、从逗号分隔的字串读入、流输入输出等功
>能。……
CStringList实现了迭代器模式,这是一种算法与数据结构相分离的模式,当然不会再把排序等算法放到容器中。事实上我如果为它写一个简单的适配器就可以使用stl中的所有算法,包括排序、二分查找、并配合i(o)stream_iterator实现流输入输出,还可以使用很多其它算法TStringList中没有的其它算法。字符串分割的算法stl中没有,但如果你写了一个,它将不只可以用于CStringList,还可以用于std::vector<std::string>,std::vector<CString>,std::list<std::string>,std::list<CString>……这是一种成熟的模式而不是缺陷。反观VCL,TStringList中有一个Sort,TList中也有一个Sort,但如果我要对一个TCollection中的元素进行排序呢?好象都用不上。如果某一天我写了一个新的容器,还要自已为它实现一个Sort……
>Delphi的OpenTools是完全面向第三方的开放系统,开发者可以修改很多Borland公司自身的功能,
>从IDE的可扩充性上说Delphi更好。
我个人比较喜欢Delphi/BCB的IDE,但关于可扩充性上我要为VC说一句公道话。虽然Delphi/BCB的OpenTools灵活强大,几乎什么都可以做(包括写一个病毒),但使用起来不是很容易;而VC中的宏相比之下很简单好用,很多在VC中很容易写的宏在Delphi中要写一大段代码来实现,而这些扩充其实是很常见的。一个功能强大,一个简单好用,两个相比不能说谁强过了谁。如果把两种方法结合起来——简单的事情由宏实现,复杂的问题写复杂的代码——这样会用起来更方便。
>即使你不使用MFC框架,花点时间看一下MFC的封装机制对你熟悉C++的OOP机制和Windows底层功能也
>是很有好处的。
熟悉Windows底层是有的,但MFC并不代表C++的OOP机制。事实上,在GUI方面,MFC可以说只是对Windows API的最简单的封装,几乎每一个方法都可以在Windows API中找到对应版本——只是少了个Handle参数,并且到处都能看到Windows消息出现。MFC中比较值得一提的是内置的文档—视图模式(MVC模式的一个变种)和对永久化的支持,不过文档—视图模式在遇到不需要这种模式的应用时反而增加了复杂度,在VC5中这一点尤其明显,不过在VC6中这一模式成为可选项了。VC中的永久化初上手用的时候很方便,但更多时候我们需要严格控制文件格式,这时它的帮助就不大的;并且它的实现还忽略了一个永久化时应该处理的重要问题——字节序问题。
事实上MFC应该说是一个成功的Windows下的GUI框架,但不能说它是一个优秀的框架,与QT或是wxWindows相比差得很远,即使是MS的工程师也承认:“MFC其实是一个失败的作品。”但由于各种原因(比较兼容旧版本),MFC很难作出什么改动。MS恐怕也没有想过再对它进行改动,在多年前就已经开始酝酿.Net了,最终目标就是让大家转到.Net框架上,这样对MFC动大手术就成了没有必要的举动。
>C++Builder似乎是个不错的折衷选择了?再仔细想想!C++Builder的优点Delphi都有,但Delphi的
>优点C++Builder未必有。比如C++Builder的编译速度比VC还慢,哪能和Delphi比?
我可不这样想,BCB一直是我比较喜欢的开发工具,如果它的编译优化实现得再好一些就是我最喜欢的了。与用Delphi相比,BCB并非是有破坏无建设,在BCB中,我可以使用STL容器和算法(VCL在这方面做得还不够),还可以使用boost、loki等第三方库的能力,并把这些都和VCL对象结合在一起使用,非常方便。我可以使用RAII来处理异常,用scoped_lock来加锁和解锁,不用再在代码中写丑陋的try-finally。可能最大的缺点就是没有message handler方法,不得不用多分支语句来完成Windows消息的分派(不要去看那些丑陋的宏,其实就是switch、case、default)——和MFC学的,不过这些只是在你需要自己处理Windows消息时才用到,由于VCL的优秀封装,这种情况并不常见。
>COM是Microsoft制订的行业标准。但Delphi也为COM提供了强大的语言支持。支持接口、variant、
>宽字符串功能。这些对COM的封装确实比C++更方便。
C/C++最重要的思想就是“语言没有能力,由库来实现”,不使用框架如果是指不使用任何程序库的话,那你还能用C/C++做什么?Delphi中内置支持确实不错,但我在VC中用_com_ptr_t、variant_t、bstr_t也并没有感到不方便。注意这些类并不是ATL或是MFC的内容,它们是独立存在的。在这里C++体现了它强大的类型扩充能力,有什么不满意的还可以再扩充。而Object Pascal由于没有这种能力(需要值对象+自定义操作符+模板),只能由语言支持,但支持得不好的情况你也只能忍受。在D6中在Variant中存放无符号整数有问题:它用_VarToInt来转换到无符号整数,虽然D5中也是这样做的,但D6中这个单元加进了整数溢出检查,结果只能有一半的无符号整数放到Variant中并成功取出来。WordBool放到Variant也有问题:当内容是true时,它会转换为bool的true,然后这个值会直接返回,这是一个整数1,而WordBool的逻辑是true是-1,结果判断为假。这两个问题都是我在项目中遇到的。还有前一段时间遇到主要时间花费在OleVaraint的释放上——1w个左右要180秒,我改用内部类型存储后只要1xx毫秒,不知道是COM的问题还是Object Pascal的问题。
还有无观紧要的一点:Borland的成名作应该是SK而不是Turbo Pascal,SK在Turbo Pascal之前就取得了成功,它的用户远比Turbo Pascal的用户多——尽管它是防拷贝的而Turbo Pascal没有。记得当年学习汇编时我就是用SK进行源代码编辑(当然,是D版的)。Turbo Pascal是一个里程碑式的产品,但它对Borland的重要性远比不上它对Pascal的重要性。Turbo C的成功才是Borland的开发工具上的里程碑,而这一成功其实是Turbo Debuger带来的——尽管TC的“一次扫描编译”听上去很让人激动。后来到了BC系列,Borland的IDE和工具才真正体现出优点来,尤其是Resouse WorkShop,它的出现让程序员不再需要在坐标纸上描对话框,可以说是最早的成功的“可视化编程”概念——RC文件也是程序,不是吗?
#34
说的好,顶
#35
称为BORLAND为Inprise的文章一般已经有些旧了。因为当BORLAND更名为INPRISE时,是它最糟糕的时候,也就是DELPHI4的时代,幸好BORLAND后来挺过来了。
#36
汗,插不上嘴
#37
我觉得Object Pascal要求显式指明override是很不错的设计————同意
Object Pascal的析构函数可以不override,不太合理————基本同意(在你不确定的情况下,还是override一下,然后在里面inherited一下)
在C++中如果基类的析构函数是虚的,衍生类的析构也必然是虚的并且是一个override————同意(因为C++的析构函数只能有一个,它会自动调用,如果多个,编译器怎么自动判断呢?不象构造函数,可以给参数什么的来判断的。)
我一直不明白多个析构函数有什么用————同意(我也不太明白,:),或许是因为OP的析构函数要自己调用,所以用户可以自己选择吧。但是为什么要多个呢?为什么呢?有这个必要吗?)
C++中构造和析构函数对基类构造和析构函数的调用是强制性的,其中析构函数是自动调用,构造函数中的指定调用,不指定则调用缺省构造,没有缺省构造则编译出错。而OP中构造和析构函数都可以不调用基类中的相关函数,容易出现Bug。————不同意(不同意你的看法,当然你说的现象是存在的,“C++中构造和析构函数对基类构造和析构函数的调用是强制性的”,因为C++的对象默认是建立在栈上的,生命周期确定,所以什么时候调用构造和析构函数的时间是确定的,而OP则不然。如果C++的对象通过NEW在堆上建立,那创建的时间也是确定的,析构也是确定的,DELETE的时候就调用喽,但是OP又不是。所以OP中的处理方法是你用户自己去决定什么时候构造类对象和析构它。‘而OP中构造和析构函数都可以不调用基类中的相关函数,容易出现Bug’,为什么不调用呢?你不管三七二十一,你inherited一下总归不会出错吧,可以不inherited是因为OP的析构函数是用户自己调用的,所以可以有多个,所以可能基类中没有这个析构函数,所以你可以不inherited,但是这不是你不inherited的原因)
OP中有抽象方法的类也可以创建,只有当某一天代码调用到了这个抽象方法时才会出错;而C++中有未override的纯虚函数的类是不允许实例化的,这一点我更喜欢C++的处理。————(对这一点,我理解不深,不敢评论)
说的不对,请大家批评。
偶是脆鸟。
:)
Object Pascal的析构函数可以不override,不太合理————基本同意(在你不确定的情况下,还是override一下,然后在里面inherited一下)
在C++中如果基类的析构函数是虚的,衍生类的析构也必然是虚的并且是一个override————同意(因为C++的析构函数只能有一个,它会自动调用,如果多个,编译器怎么自动判断呢?不象构造函数,可以给参数什么的来判断的。)
我一直不明白多个析构函数有什么用————同意(我也不太明白,:),或许是因为OP的析构函数要自己调用,所以用户可以自己选择吧。但是为什么要多个呢?为什么呢?有这个必要吗?)
C++中构造和析构函数对基类构造和析构函数的调用是强制性的,其中析构函数是自动调用,构造函数中的指定调用,不指定则调用缺省构造,没有缺省构造则编译出错。而OP中构造和析构函数都可以不调用基类中的相关函数,容易出现Bug。————不同意(不同意你的看法,当然你说的现象是存在的,“C++中构造和析构函数对基类构造和析构函数的调用是强制性的”,因为C++的对象默认是建立在栈上的,生命周期确定,所以什么时候调用构造和析构函数的时间是确定的,而OP则不然。如果C++的对象通过NEW在堆上建立,那创建的时间也是确定的,析构也是确定的,DELETE的时候就调用喽,但是OP又不是。所以OP中的处理方法是你用户自己去决定什么时候构造类对象和析构它。‘而OP中构造和析构函数都可以不调用基类中的相关函数,容易出现Bug’,为什么不调用呢?你不管三七二十一,你inherited一下总归不会出错吧,可以不inherited是因为OP的析构函数是用户自己调用的,所以可以有多个,所以可能基类中没有这个析构函数,所以你可以不inherited,但是这不是你不inherited的原因)
OP中有抽象方法的类也可以创建,只有当某一天代码调用到了这个抽象方法时才会出错;而C++中有未override的纯虚函数的类是不允许实例化的,这一点我更喜欢C++的处理。————(对这一点,我理解不深,不敢评论)
说的不对,请大家批评。
偶是脆鸟。
:)
#38
我觉得Object Pascal要求显式指明override是很不错的设计————同意
Object Pascal的析构函数可以不override,不太合理————基本同意(在你不确定的情况下,还是override一下,然后在里面inherited一下)
在C++中如果基类的析构函数是虚的,衍生类的析构也必然是虚的并且是一个override————同意(因为C++的析构函数只能有一个,它会自动调用,如果多个,编译器怎么自动判断呢?不象构造函数,可以给参数什么的来判断的。)
我一直不明白多个析构函数有什么用————同意(我也不太明白,:),或许是因为OP的析构函数要自己调用,所以用户可以自己选择吧。但是为什么要多个呢?为什么呢?有这个必要吗?)
C++中构造和析构函数对基类构造和析构函数的调用是强制性的,其中析构函数是自动调用,构造函数中的指定调用,不指定则调用缺省构造,没有缺省构造则编译出错。而OP中构造和析构函数都可以不调用基类中的相关函数,容易出现Bug。————不同意(不同意你的看法,当然你说的现象是存在的,“C++中构造和析构函数对基类构造和析构函数的调用是强制性的”,因为C++的对象默认是建立在栈上的,生命周期确定,所以什么时候调用构造和析构函数的时间是确定的,而OP则不然。如果C++的对象通过NEW在堆上建立,那创建的时间也是确定的,析构也是确定的,DELETE的时候就调用喽,但是OP又不是。所以OP中的处理方法是你用户自己去决定什么时候构造类对象和析构它。‘而OP中构造和析构函数都可以不调用基类中的相关函数,容易出现Bug’,为什么不调用呢?你不管三七二十一,你inherited一下总归不会出错吧,可以不inherited是因为OP的析构函数是用户自己调用的,所以可以有多个,所以可能基类中没有这个析构函数,所以你可以不inherited,但是这不是你不inherited的原因)
OP中有抽象方法的类也可以创建,只有当某一天代码调用到了这个抽象方法时才会出错;而C++中有未override的纯虚函数的类是不允许实例化的,这一点我更喜欢C++的处理。————(对这一点,我理解不深,不敢评论)
说的不对,请大家批评。
偶是脆鸟。
:)
Object Pascal的析构函数可以不override,不太合理————基本同意(在你不确定的情况下,还是override一下,然后在里面inherited一下)
在C++中如果基类的析构函数是虚的,衍生类的析构也必然是虚的并且是一个override————同意(因为C++的析构函数只能有一个,它会自动调用,如果多个,编译器怎么自动判断呢?不象构造函数,可以给参数什么的来判断的。)
我一直不明白多个析构函数有什么用————同意(我也不太明白,:),或许是因为OP的析构函数要自己调用,所以用户可以自己选择吧。但是为什么要多个呢?为什么呢?有这个必要吗?)
C++中构造和析构函数对基类构造和析构函数的调用是强制性的,其中析构函数是自动调用,构造函数中的指定调用,不指定则调用缺省构造,没有缺省构造则编译出错。而OP中构造和析构函数都可以不调用基类中的相关函数,容易出现Bug。————不同意(不同意你的看法,当然你说的现象是存在的,“C++中构造和析构函数对基类构造和析构函数的调用是强制性的”,因为C++的对象默认是建立在栈上的,生命周期确定,所以什么时候调用构造和析构函数的时间是确定的,而OP则不然。如果C++的对象通过NEW在堆上建立,那创建的时间也是确定的,析构也是确定的,DELETE的时候就调用喽,但是OP又不是。所以OP中的处理方法是你用户自己去决定什么时候构造类对象和析构它。‘而OP中构造和析构函数都可以不调用基类中的相关函数,容易出现Bug’,为什么不调用呢?你不管三七二十一,你inherited一下总归不会出错吧,可以不inherited是因为OP的析构函数是用户自己调用的,所以可以有多个,所以可能基类中没有这个析构函数,所以你可以不inherited,但是这不是你不inherited的原因)
OP中有抽象方法的类也可以创建,只有当某一天代码调用到了这个抽象方法时才会出错;而C++中有未override的纯虚函数的类是不允许实例化的,这一点我更喜欢C++的处理。————(对这一点,我理解不深,不敢评论)
说的不对,请大家批评。
偶是脆鸟。
:)
#39
晕,怎么发了两次啊?我那些是发给(短歌)的,呵呵.
#40
多谢!再顶。
#41
对API的封装不同.
#42
不错。继续讨论
#43
顶,不错!
#44
MK.
我觉得OO只是面向对象 跟具体的语言是无关的 只不过不同的语言对OO的支持的方法,形式不同而已
对CPP / OP 了解都不是很深 不敢妄言~~~
我觉得OO只是面向对象 跟具体的语言是无关的 只不过不同的语言对OO的支持的方法,形式不同而已
对CPP / OP 了解都不是很深 不敢妄言~~~
#45
回复人: longtusoft(神灯之主) ( ) 信誉:97 2004-10-6 23:07:00 得分: 0
对API的封装不同.
------------
呵呵 不是这样的哦。这里根本就不牵涉到具体的什么API....
对API的封装不同.
------------
呵呵 不是这样的哦。这里根本就不牵涉到具体的什么API....
#46
ding
#47
听课...
#48
大同小异,没什么大区别,
#49
C++和Delphi 都是由结构化语言进化来的OO语言,为了保持与前期语言(C和PASCAL)的兼容性,都存在一些缺陷.
我个人使用C++和DELPHI的感觉来讲,C++的特点之一:灵活性,使它比较难于全面掌握,C++中有太多的特殊情况了;而DELPHI相对简化了很多,比较容易上手.
最近2年少用C++了,对C++有"不满"的同志们可以看看这本书,心情可能会好些,呵呵!
《对象揭秘: Java、Eiffel和C++》 Ian Joyner著 鲍志云 译 人民邮电出版社
我个人使用C++和DELPHI的感觉来讲,C++的特点之一:灵活性,使它比较难于全面掌握,C++中有太多的特殊情况了;而DELPHI相对简化了很多,比较容易上手.
最近2年少用C++了,对C++有"不满"的同志们可以看看这本书,心情可能会好些,呵呵!
《对象揭秘: Java、Eiffel和C++》 Ian Joyner著 鲍志云 译 人民邮电出版社
#50
已阅
^_^
^_^
#1
C++支持多继承,Delphi不支持,你看看设计模式吧,很有帮助的,不过小程序很难体现优点的。
#2
我把查询模块都封装成了class,当然是符合流程的了,delphi编写的,
vc编写人事管理系统的时候,个别的class都写成了抽象类,感觉还行,其他几个人都在继承继续编写。
vc编写人事管理系统的时候,个别的class都写成了抽象类,感觉还行,其他几个人都在继承继续编写。
#3
关注
#4
我以前也是用VC的,现正学delphi,对这个问题也较感兴趣。我觉得应从两个方面看,一是object pascal与c++比较,C++更灵活,它支持操作符重载、多继承和模板,因此可实现泛型编程如WTL、STL等。pascal不支持操作符重载和模板,它的接口机制可实现多继承相似的东西。这并不是说c++比pascal更强大,从编程角度讲,没有彼此不能实现的算法。二是从开发环境来讲,DELPHI 比VISUAL C++ 的组件封装更全面、更简洁,因些更适合快速开发应用程序。VC涉及的低层东西较多,开发出的程序更稳健更紧凑,手工代码较多。因此更适合作低层工作。当然,只要你原意,两者可以做所有的WINDOWS平台上的开发,只是速度和效率不一样而已。这就看我们具体要做什么工作了。另外我个人的感受是C++语法更简单,msdn更是在线帮助中的精品,如果项目时间允许,慢一点也原意用它。
#5
delphi实用
#6
Delphi所有的类都必须从TObject继承下来的~~ //这点我不太喜欢哦~~
而C++则没有这个限制~~
C是由汇编演变过来的,是高级语言中最接近机器指令的语言~~
Pascal则是为了教学而设计的,初衷是培养程序员严谨和良好的编程风格~~
网上流传着:真正的程序员用C、聪明的程序员用Delphi~~
其实是废话,
真正的程序员不管用什么还是真正的程序员~~
聪明的程序员不管用什么还是聪明的程序员~~
:)
而C++则没有这个限制~~
C是由汇编演变过来的,是高级语言中最接近机器指令的语言~~
Pascal则是为了教学而设计的,初衷是培养程序员严谨和良好的编程风格~~
网上流传着:真正的程序员用C、聪明的程序员用Delphi~~
其实是废话,
真正的程序员不管用什么还是真正的程序员~~
聪明的程序员不管用什么还是聪明的程序员~~
:)
#7
zswang(伴水清清)的一针见血
#8
还是摆脱语言的困惑吧.
全世界的人,用什么语言都可以交流,难道你能说
哪种语言先进,哪种语言落后.
哪种语言好,哪种语言不好?
全世界的人,用什么语言都可以交流,难道你能说
哪种语言先进,哪种语言落后.
哪种语言好,哪种语言不好?
#9
Delphi所有的类都必须从TObject继承下来的//这点我非常喜欢...嘻嘻
#10
有很多。PASCAL的语法也比较严格的
#11
to zswang(伴水清清)
你错了,并不是非要从TObject继承下来
你可以测试下!
TClass = object
public
class procedure Create;
end;
这样的声明是可以的,它并不是从TObject继承的
一般写法为:
TClass= class //这里省略了TObject 但实际是从TObject继承
end;
但是象上面使用object来定义的类怎么使用,我还不太清楚!
你错了,并不是非要从TObject继承下来
你可以测试下!
TClass = object
public
class procedure Create;
end;
这样的声明是可以的,它并不是从TObject继承的
一般写法为:
TClass= class //这里省略了TObject 但实际是从TObject继承
end;
但是象上面使用object来定义的类怎么使用,我还不太清楚!
#12
TO :楼上
这个就合C++一样,不再堆上分配!也不用调用TXXXX.Create
当你
Var
时,就直接调用构造函数了
这个和Turbo Pascal 5.5+ 是一样的!
这个就合C++一样,不再堆上分配!也不用调用TXXXX.Create
当你
Var
时,就直接调用构造函数了
这个和Turbo Pascal 5.5+ 是一样的!
#13
Test = object
a:integer;
b:integer;
function geta:integer;
end;
function test.geta:integer;
begin
result:=a;
end;
var aa:Test;
aa.a:=100;
aa.geta;
...
我一直这样用,只是不要使用virtual 方法
a:integer;
b:integer;
function geta:integer;
end;
function test.geta:integer;
begin
result:=a;
end;
var aa:Test;
aa.a:=100;
aa.geta;
...
我一直这样用,只是不要使用virtual 方法
#14
to zwjchina:
虽然对象类型确实是早期面向对象使用的类型~~
但对象类型和类类型是不同类型 :)~~
所以你说我错,我可不同意~~
对象类型不需要构造和析构就可以使用,更象是记录类型~~
Borland语言手册中写:“对象类型存在的目的是为了与旧有但程序兼容,所以并不建议使用它”~~
不过人的想象力是无穷的,就象Kol就是利用对象类型,精简编译出来的代码~~
虽然对象类型确实是早期面向对象使用的类型~~
但对象类型和类类型是不同类型 :)~~
所以你说我错,我可不同意~~
对象类型不需要构造和析构就可以使用,更象是记录类型~~
Borland语言手册中写:“对象类型存在的目的是为了与旧有但程序兼容,所以并不建议使用它”~~
不过人的想象力是无穷的,就象Kol就是利用对象类型,精简编译出来的代码~~
#15
谈论语言间的本质区别应该从编译器实现角度去考虑,毕竟语言是编译器直接处理的对象,语言的一切语法和语意都是和具体编译器实现直接关联的。
语言学习中有一个方面是对象模型,如果楼主注意,可以发现很多语言的对象模型都是非常雷同的,包括现在很流行的基于中间指令的语言,比如Java和C Sharp等等。
对于支持OO的语言无非也是在编译实现和对象模型实现上直接建立内存表格与类或其他语言元素对应以形成支持的,从语言角度来讲,个人认为本质上没有什么大的区别。
楼上有人说继承方面的区别那是区别,但不是本质区别。
语言学习中有一个方面是对象模型,如果楼主注意,可以发现很多语言的对象模型都是非常雷同的,包括现在很流行的基于中间指令的语言,比如Java和C Sharp等等。
对于支持OO的语言无非也是在编译实现和对象模型实现上直接建立内存表格与类或其他语言元素对应以形成支持的,从语言角度来讲,个人认为本质上没有什么大的区别。
楼上有人说继承方面的区别那是区别,但不是本质区别。
#16
我想说的是微软实在太强了
#17
从pascal和c起就有分别了。而且影响了c++和delphi的风格,比较一下vcl和owl。
#18
C++灵活
Delphi简洁
Delphi简洁
#19
什么语言都有,存在就是合理,选择适用好用的,熟手的就是了:)
单根继承也有他的有点的:)新的语言似乎都看中了单根继承的好处:)
我记得Delphi的都是Tobject继承来的,你不声明都是默认TObject的,他是单根的
C#,感觉是Delphi+VC的东西:)
http://lysoft.7u7.net
单根继承也有他的有点的:)新的语言似乎都看中了单根继承的好处:)
我记得Delphi的都是Tobject继承来的,你不声明都是默认TObject的,他是单根的
C#,感觉是Delphi+VC的东西:)
http://lysoft.7u7.net
#20
to zswang
呵呵,和高手讨论就是不一样,本来我认为理所当然的没想到你还可以找到理由反驳!
不过对你的理由,我却不大同意!
想当初C++的类不一样也是带方法的结构,这和OPP的带方法的记录不也是一回事情么?
只不过发展到现在,都把分配对象类存的过程统一到对象构造方法中了!
呵呵,和高手讨论就是不一样,本来我认为理所当然的没想到你还可以找到理由反驳!
不过对你的理由,我却不大同意!
想当初C++的类不一样也是带方法的结构,这和OPP的带方法的记录不也是一回事情么?
只不过发展到现在,都把分配对象类存的过程统一到对象构造方法中了!
#21
只不过发展到现在,都把分配对象,内存的过程统一到对象构造方法中了!
#22
有人在问我:先有鸡还是先有蛋?~~
那么我会反问:
是不是鸡下的蛋都是鸡蛋?
是不是能孵出鸡的蛋都是鸡蛋?
是不是鸡蛋孵出的都是鸡?
是不是能下出鸡蛋的都是鸡?
如果对鸡和蛋的定义本来就是矛盾的,那这个问题则没有答案~~
问题本来是错的,怎么又有正确的答案呢~~
同样我想问zwjchina
class声明出来的叫类
object声明出来的也就类?
那照阁下所说,所有数据的是由0和1组成的,它们本质就没有任何区别~~
所以看来是我错了!~~
那么我会反问:
是不是鸡下的蛋都是鸡蛋?
是不是能孵出鸡的蛋都是鸡蛋?
是不是鸡蛋孵出的都是鸡?
是不是能下出鸡蛋的都是鸡?
如果对鸡和蛋的定义本来就是矛盾的,那这个问题则没有答案~~
问题本来是错的,怎么又有正确的答案呢~~
同样我想问zwjchina
class声明出来的叫类
object声明出来的也就类?
那照阁下所说,所有数据的是由0和1组成的,它们本质就没有任何区别~~
所以看来是我错了!~~
#23
谢谢大家的讨论!
对于“delphi所有的类都必须从TObject继承下来的”这一观点, ly_liuyang(Liu Yang)理解的对,
因为OOP是一种严谨的语言,它对很多在C/C++可以由程序员*发挥的地方做了很多的限制。如果在你的类定义中没有声明它的父类,delphi会默认为TObject类。
这里我还要再次声明一下,提出这个问题,并不是想去比较两种语言孰优孰劣或是该用哪种语言去实现或是用哪一个开发工具。只是想从计算机语言学的角度来比较两种语言的区别和相同的地方。
对于“delphi所有的类都必须从TObject继承下来的”这一观点, ly_liuyang(Liu Yang)理解的对,
因为OOP是一种严谨的语言,它对很多在C/C++可以由程序员*发挥的地方做了很多的限制。如果在你的类定义中没有声明它的父类,delphi会默认为TObject类。
这里我还要再次声明一下,提出这个问题,并不是想去比较两种语言孰优孰劣或是该用哪种语言去实现或是用哪一个开发工具。只是想从计算机语言学的角度来比较两种语言的区别和相同的地方。
#24
听课!!
#25
Object Pascal中的对象单根体系,而C++中无此限制,这是严谨与灵活的区别。
Object Pascal中的对象天生是引用语义,而C++中的对象是值语义。上面有人提到的object类型属于过时的内容,继续保留它只是为了兼容以前的版本,现在完全不用把它看成是Object Pascal中的一个内容,也是由于这个原因,帮助中对这个类型讲得不是很详细,我没有找到为他定义构造、析构以及多态函数的方法(用class类型的方法是不行的)。C++的值对象的一大特点就是自动构造和析构,即使有异常抛出析构也会进行,这样在代码中就减少了try-finally的存在必要;这一特点配合C++的泛型能力更是发展出了RAII技术,使得在C++中异常安全代码的实现更加简化了。比如我在BCB中可以这样写:
{
std::auto_ptr<TForm2> ADlg (new TForm2(NULL));
if (ADlg->ShowModal() == mrOK)
{
...
}
}
而在Delphi中不得不:
var
ADlg: TForm2;
begin
ADlg := TForm2.Create(nil);
try
if ADlg.ShowModal = mrOK then
begin
...
end;
finally
ADlg.Free;
end;
end;
如果一个函数中需要注意释放的资源比较多这种情况更加严重,将会由于多个try-finally嵌套的情况而影响代码可读性。我觉得这一点是Object Pascal的缺点。与C++相比,Object Pascal才是急需引入垃圾回收机制的语言。
Object Pascal中的类没有多继承,但有interface关键字,一个类可以实现多个interface;而C++中则没有interface概念,使用多继承+抽象类来实现这一点,但也可以多继承自普通的类。一般来说,所有目的是重用的继承都可以被组合方式代替,而作为“子类型”的概念,interface概念已经表达得很清楚了,所以这一点上没有多继承并没有什么明显的缺陷。
事实上,在面向对象编程方面,Object Pascal与Java和C#更加接近,不同的是它不是运行在虚拟机中的,也没有垃圾回收机制。
Object Pascal中的对象天生是引用语义,而C++中的对象是值语义。上面有人提到的object类型属于过时的内容,继续保留它只是为了兼容以前的版本,现在完全不用把它看成是Object Pascal中的一个内容,也是由于这个原因,帮助中对这个类型讲得不是很详细,我没有找到为他定义构造、析构以及多态函数的方法(用class类型的方法是不行的)。C++的值对象的一大特点就是自动构造和析构,即使有异常抛出析构也会进行,这样在代码中就减少了try-finally的存在必要;这一特点配合C++的泛型能力更是发展出了RAII技术,使得在C++中异常安全代码的实现更加简化了。比如我在BCB中可以这样写:
{
std::auto_ptr<TForm2> ADlg (new TForm2(NULL));
if (ADlg->ShowModal() == mrOK)
{
...
}
}
而在Delphi中不得不:
var
ADlg: TForm2;
begin
ADlg := TForm2.Create(nil);
try
if ADlg.ShowModal = mrOK then
begin
...
end;
finally
ADlg.Free;
end;
end;
如果一个函数中需要注意释放的资源比较多这种情况更加严重,将会由于多个try-finally嵌套的情况而影响代码可读性。我觉得这一点是Object Pascal的缺点。与C++相比,Object Pascal才是急需引入垃圾回收机制的语言。
Object Pascal中的类没有多继承,但有interface关键字,一个类可以实现多个interface;而C++中则没有interface概念,使用多继承+抽象类来实现这一点,但也可以多继承自普通的类。一般来说,所有目的是重用的继承都可以被组合方式代替,而作为“子类型”的概念,interface概念已经表达得很清楚了,所以这一点上没有多继承并没有什么明显的缺陷。
事实上,在面向对象编程方面,Object Pascal与Java和C#更加接近,不同的是它不是运行在虚拟机中的,也没有垃圾回收机制。
#26
>呵呵,和高手讨论就是不一样,本来我认为理所当然的没想到你还可以找到理由反驳!
>不过对你的理由,我却不大同意!
>想当初C++的类不一样也是带方法的结构,这和OPP的带方法的记录不也是一回事情么?
>只不过发展到现在,都把分配对象类存的过程统一到对象构造方法中了!
这这说法我不能赞同,在C++第一个“标准”——AT&T C++1.0文档中,C++中的类就不只是“带方法的结构”,它支持构造函数的析构函数,最重要的是支持多态。封装、继承与多态是面向对象的三大基本特性,VB一直不被认为是面向对象编程语言的原因正是在于缺乏对继承和多态的支持(VB.Net已经加入了这方面的内容),把“类”仅仅理解为“带方法的结构”不符合面向对象编程的要求。
>不过对你的理由,我却不大同意!
>想当初C++的类不一样也是带方法的结构,这和OPP的带方法的记录不也是一回事情么?
>只不过发展到现在,都把分配对象类存的过程统一到对象构造方法中了!
这这说法我不能赞同,在C++第一个“标准”——AT&T C++1.0文档中,C++中的类就不只是“带方法的结构”,它支持构造函数的析构函数,最重要的是支持多态。封装、继承与多态是面向对象的三大基本特性,VB一直不被认为是面向对象编程语言的原因正是在于缺乏对继承和多态的支持(VB.Net已经加入了这方面的内容),把“类”仅仅理解为“带方法的结构”不符合面向对象编程的要求。
#27
zswang(伴水清清)(专家门诊清洁工)
:Delphi所有的类都必须从TObject继承下来的~~ //这点我不太喜欢哦~~
我就比较喜欢所有的类都从一个基类派生!
:Delphi所有的类都必须从TObject继承下来的~~ //这点我不太喜欢哦~~
我就比较喜欢所有的类都从一个基类派生!
#28
也可以这样写,少用一个变量
with TForm2.Create(nil) do
begin
if ShowModal = mrOK then
begin
...
end;
free;
end;
object 类有的时候还是可以当record一样用一下,不用Create,free
with TForm2.Create(nil) do
begin
if ShowModal = mrOK then
begin
...
end;
free;
end;
object 类有的时候还是可以当record一样用一下,不用Create,free
#29
也可以这样写,少用一个变量
with TForm2.Create(nil) do
begin
try
if ShowModal = mrOK then
begin
...
end;
finally
free;
end;
end;
少了try-finally
不过我不喜欢用with,一旦用了with A do,A的成员就可以直接访问而不用加限定符(我是指那个“A.”)了,如果和以有的不需要限定符的符号(比如Self.XXX)同名就会导致歧义。最头痛的是,当歧义发生时,Object Pascal不告诉你而是替你选择一个,很可能不导致语法错误。在我参与的项目中遇到过好几次问题都是因为使用了一个with,结果找了好久才知道错误在什么地方。
我觉得用object类型当record用没有什么特别的好处,成员函数我完全可以用全局函数代替。
到OO方面的实现细节方面:
我觉得Object Pascal要求显式指明override是很不错的设计,这样避免了由于输入错误导致本想override却成了定义新方法。而在C++仅依靠名字进行判断,如果在衍生类中进行override时输入错了,结果就成了衍生类定义的新方法,编译通过,结果不正确……除非基类中的虚函数都是纯的,子类不override的话不能创建。
Object Pascal的析构函数可以不override,不太合理。在C++中如果基类的析构函数是虚的,衍生类的析构也必然是虚的并且是一个override,因为C++析构函数只能有一个,而OP可以有多个(我一直不明白多个析构函数有什么用)。
C++中构造和析构函数对基类构造和析构函数的调用是强制性的,其中析构函数是自动调用,构造函数中的指定调用,不指定则调用缺省构造,没有缺省构造则编译出错。而OP中构造和析构函数都可以不调用基类中的相关函数,容易出现Bug。
OP中有抽象方法的类也可以创建,只有当某一天代码调用到了这个抽象方法时才会出错;而C++中有未override的纯虚函数的类是不允许实例化的,这一点我更喜欢C++的处理。
非OO方面我最讨厌的是两个问题:
1:OP对指针类型转换的检查太弱了!远没有C++严格——谁说OP一定比C++严谨?
2:C++数组可以隐式转换为指针并且指针可以当数组访问,很另人头痛,不如象OP那样用“指向数组的指针”,不容易出错。
with TForm2.Create(nil) do
begin
try
if ShowModal = mrOK then
begin
...
end;
finally
free;
end;
end;
少了try-finally
不过我不喜欢用with,一旦用了with A do,A的成员就可以直接访问而不用加限定符(我是指那个“A.”)了,如果和以有的不需要限定符的符号(比如Self.XXX)同名就会导致歧义。最头痛的是,当歧义发生时,Object Pascal不告诉你而是替你选择一个,很可能不导致语法错误。在我参与的项目中遇到过好几次问题都是因为使用了一个with,结果找了好久才知道错误在什么地方。
我觉得用object类型当record用没有什么特别的好处,成员函数我完全可以用全局函数代替。
到OO方面的实现细节方面:
我觉得Object Pascal要求显式指明override是很不错的设计,这样避免了由于输入错误导致本想override却成了定义新方法。而在C++仅依靠名字进行判断,如果在衍生类中进行override时输入错了,结果就成了衍生类定义的新方法,编译通过,结果不正确……除非基类中的虚函数都是纯的,子类不override的话不能创建。
Object Pascal的析构函数可以不override,不太合理。在C++中如果基类的析构函数是虚的,衍生类的析构也必然是虚的并且是一个override,因为C++析构函数只能有一个,而OP可以有多个(我一直不明白多个析构函数有什么用)。
C++中构造和析构函数对基类构造和析构函数的调用是强制性的,其中析构函数是自动调用,构造函数中的指定调用,不指定则调用缺省构造,没有缺省构造则编译出错。而OP中构造和析构函数都可以不调用基类中的相关函数,容易出现Bug。
OP中有抽象方法的类也可以创建,只有当某一天代码调用到了这个抽象方法时才会出错;而C++中有未override的纯虚函数的类是不允许实例化的,这一点我更喜欢C++的处理。
非OO方面我最讨厌的是两个问题:
1:OP对指针类型转换的检查太弱了!远没有C++严格——谁说OP一定比C++严谨?
2:C++数组可以隐式转换为指针并且指针可以当数组访问,很另人头痛,不如象OP那样用“指向数组的指针”,不容易出错。
#30
转在网上看到的一篇文章,也许对楼主理解所提出的问题有所帮助
开发工具大比拼之Visual C++ VS Delphi
文:紫云英、曾登高
引言
"Visual C++与Delphi之比较"最近在CSDN的论坛上的讨论非常火热,本文将以一个程序员的角度,从技术水平、功能、性能、易用性、稳定性、发展历程和前景等方面,以Visual C++6和Delphi5为代表,尽可能客观地比较介绍Visual C++和Delphi这两大主流开发工具的优缺点,其中将涉及到语言、应用框架、控件、编译和连接、集成界面、调试、COM、数据库开发等。本文还将对如何选择使用这两个开发工具提出一些建议。
值得一提的是,由于C++Builder与Delphi同为Inprise公司产品,它们除了使用的语言不同,其余特性几乎都相同。因此本文对C++Builder程序员和学习者也有参考价值。
语言:存在即是合理
首先声明常被混淆的一点:VC和Delphi本身不是语言,而是开发平台。它们所用的语言分别是略作扩展的C/C++和Object Pascal。我在网上常看到有人问应该学C/C++还是VC,这个问题很好回答:如果你学VC你就必须得学C/C++,或者说你学会了VC也就学会了C/C++了。
言归正传,我们来比较一下C++和Object Pascal的优缺点。有人认为Object Pascal是"玩具语言",C++才是"专业语言",这是不对的。单从语言本身看,Object Pascal与C++属同一重量级。它们都是完全支持面向对象的语言,都扎根于"历史悠久"的面向过程的语言。C++是由C发展而来的,Object Pascal由Pascal进化而来。它们都有很强的灵活性,都有自己的特长和不足。比如说,Object Pascal不支持多重继承、模板、操作符重载、内联函数定义、预处理、宏、全局静态类变量、嵌套类定义,等等,而这些都是C++支持的。但同样地C++也不支持Object Pascal的虚构造函数、过程嵌套、内置集合类型、内置字符串类型、"finally"构造等等,在RTTI方面Object Pascal也比C++做得好。但这些并不重要,因为可以通过其它方式达到同样的目的,比如C++可以通过类扩展支持集合、字符串,Object Pascal可以通过"interface"多重继承,等等。关键是二者都可以很好地完成你手头的任务,这就够了。
但是,仅仅比较语言本身是不够的,还得看它们的被接受和流行程度,学习曲线,发展前途,可移植性等,以及,很重要但常常被忽略的一点:与开发环境(指VC与Delphi)及其应用框架的"磨合"程度。
VC和Delphi作为开发平台,很重要的一点就是提供了一个"无所不包"的应用框架:VC的MFC和Delphi的VCL。MFC是用C++写的,VCL是用Object Pascal写的。当然,我们都知道,C++的使用范围比Object Pascal广得多,移植性也好得多。这本来是优点,但很有意思的是,正因为如此,微软写MFC时必须考虑最大限度减少对语言本身的改动,而把功夫下在源代码级,以便能尽可能支持ANSI等标准,结果导致MFC的封装复杂而不直观。(尤其是它对消息的封装,下文还会提到)。太多的宏定义和含义模糊且自动生成、不得改动的注释使MFC乃至VC让很多新手望而生畏,不敢"下水"深入学习。而Object Pascal几乎是Inprise"专用"的,不必考虑"标准"问题,因此Inprise写VCL时就把全部精力放在了结构与性能上,结果语言与框架的磨合程度非常好。VCL框架的结构清晰,VCL代码的可读性非常好。许多人说Delphi比较容易上手,也是这个缘故。天下没有白吃的午餐。你要工业标准吗?你要可移植性吗(关于可移植性和兼容性,下文会详细比较)?那么请面对MFC的"天书"级代码吧。
编译和连接:The Need For Speed
不同的语言带来的另一个不同是,编译和连接的速度的不同,以及执行速度的不同。Delphi的编译和连接速度,毫不夸张地说,比VC快几十倍。即使把VC的Incremental Link选项打开,Delphi的编译和连接速度仍比VC快好几倍。并不是说微软的编译器不行,这是由C++的复杂性决定的。模板的处理、预处理和宏的展开都是很费时的。前文不是提到Object Pascal没有模板、预处理和宏吗?这本来是缺点,但带来的一个好处就是编译速度极快。至于编译完的二进制代码,在打开相同的优化选项的情况下,Delphi和VC执行速度并没有太大的差别。
为了克服编译的速度问题,C++编译器一般需要增强的连接器和预处理机制。但是预处理机制仍然存在若干问题:1)程序调试的断点行可能和代码行不同;2)没有将最新的代码信息综合进去;3)容易产生错误的逻辑;4)因为读错文件头而很容易产生类似"Unexpected End of File"的错误。
两个编译器有个共同点是都能识别无用的"死"代码,比如一个没有用的函数等等。编译后的程序将不包含这些多余的信息。Delphi在这方面作得更加出色。它可以让你在编辑器中可视化地提示出那行代码是"活"的、那行代码是"死"的。这样你就能整理出最精简的代码。Delphi在编译后将在左边显示一个小蓝点表示这行代码是"活"的。Visual C++做不到这点。
Delphi编译后可执行文件至少有200K(如果不使用VCL,仅仅使用WinAPI,文件的大小将大大缩小)但是Visual C++编程使用MFC编译后的可执行文件通常只有几十K,主要是因为微软已经将系统运行库包含在Windows系统了(Borland公司曾经和微软协商这个接口,但是微软利用操作系统的优势不愿意公开)。同样道理,使用BDE开发的的数据库程序必须附带3-5M的额外系统文件,也是非常不协调的。
非常有趣的是,Delphi能够使用由C++ Builder创建的的OBJ文件,但是使用上受很大的局限性。
最后,Visual C++的编译和连接时的错误信息比Delphi要详细和具体的多。特别是使用ATL开发更加如此。
应用框架:MFC?有KFC流行吗?
应用程序框架(Application Frame),有时也称为对象框架。Visual C++采用的框架是MFC。MFC不仅仅是人们通常理解的一个类库(同样,Delphi的VCL也不仅仅是一个控件库,尽管它的名字叫"可视控件库")。你如果选择了MFC,也就选择了一种程序结构,一种编程风格。MFC早在Windows 3.x的时代就出现了,那时的Visual C++还是16位的。经过这些年的不断补充和完善,MFC已经十分成熟。但由于原型出现得比较早,MFC相比于VCL落后了一个时代。尽管微软对MFC的更新没有停止,我也经常读到"只要Windows不过时,MFC就不会过时"之类观点的文章,但就象Inprise(原Borland)的OWL框架的淡出一样,MFC的淡出也是早晚的事。其实MFC是和OWL同一个时代的产物。OWL已经不在了,MFC怎能不"居安思危"呢?如果MFC青春永驻,微软的开发人员也不会"私自"开发出基于ATL的WTL呀。当然,WTL的地位不能和MFC比,它并不是微软官方支持的框架,封装的功能也相当有限。但至少也反衬出了MFC存在的不足。
开发工具大比拼之Visual C++ VS Delphi
文:紫云英、曾登高
引言
"Visual C++与Delphi之比较"最近在CSDN的论坛上的讨论非常火热,本文将以一个程序员的角度,从技术水平、功能、性能、易用性、稳定性、发展历程和前景等方面,以Visual C++6和Delphi5为代表,尽可能客观地比较介绍Visual C++和Delphi这两大主流开发工具的优缺点,其中将涉及到语言、应用框架、控件、编译和连接、集成界面、调试、COM、数据库开发等。本文还将对如何选择使用这两个开发工具提出一些建议。
值得一提的是,由于C++Builder与Delphi同为Inprise公司产品,它们除了使用的语言不同,其余特性几乎都相同。因此本文对C++Builder程序员和学习者也有参考价值。
语言:存在即是合理
首先声明常被混淆的一点:VC和Delphi本身不是语言,而是开发平台。它们所用的语言分别是略作扩展的C/C++和Object Pascal。我在网上常看到有人问应该学C/C++还是VC,这个问题很好回答:如果你学VC你就必须得学C/C++,或者说你学会了VC也就学会了C/C++了。
言归正传,我们来比较一下C++和Object Pascal的优缺点。有人认为Object Pascal是"玩具语言",C++才是"专业语言",这是不对的。单从语言本身看,Object Pascal与C++属同一重量级。它们都是完全支持面向对象的语言,都扎根于"历史悠久"的面向过程的语言。C++是由C发展而来的,Object Pascal由Pascal进化而来。它们都有很强的灵活性,都有自己的特长和不足。比如说,Object Pascal不支持多重继承、模板、操作符重载、内联函数定义、预处理、宏、全局静态类变量、嵌套类定义,等等,而这些都是C++支持的。但同样地C++也不支持Object Pascal的虚构造函数、过程嵌套、内置集合类型、内置字符串类型、"finally"构造等等,在RTTI方面Object Pascal也比C++做得好。但这些并不重要,因为可以通过其它方式达到同样的目的,比如C++可以通过类扩展支持集合、字符串,Object Pascal可以通过"interface"多重继承,等等。关键是二者都可以很好地完成你手头的任务,这就够了。
但是,仅仅比较语言本身是不够的,还得看它们的被接受和流行程度,学习曲线,发展前途,可移植性等,以及,很重要但常常被忽略的一点:与开发环境(指VC与Delphi)及其应用框架的"磨合"程度。
VC和Delphi作为开发平台,很重要的一点就是提供了一个"无所不包"的应用框架:VC的MFC和Delphi的VCL。MFC是用C++写的,VCL是用Object Pascal写的。当然,我们都知道,C++的使用范围比Object Pascal广得多,移植性也好得多。这本来是优点,但很有意思的是,正因为如此,微软写MFC时必须考虑最大限度减少对语言本身的改动,而把功夫下在源代码级,以便能尽可能支持ANSI等标准,结果导致MFC的封装复杂而不直观。(尤其是它对消息的封装,下文还会提到)。太多的宏定义和含义模糊且自动生成、不得改动的注释使MFC乃至VC让很多新手望而生畏,不敢"下水"深入学习。而Object Pascal几乎是Inprise"专用"的,不必考虑"标准"问题,因此Inprise写VCL时就把全部精力放在了结构与性能上,结果语言与框架的磨合程度非常好。VCL框架的结构清晰,VCL代码的可读性非常好。许多人说Delphi比较容易上手,也是这个缘故。天下没有白吃的午餐。你要工业标准吗?你要可移植性吗(关于可移植性和兼容性,下文会详细比较)?那么请面对MFC的"天书"级代码吧。
编译和连接:The Need For Speed
不同的语言带来的另一个不同是,编译和连接的速度的不同,以及执行速度的不同。Delphi的编译和连接速度,毫不夸张地说,比VC快几十倍。即使把VC的Incremental Link选项打开,Delphi的编译和连接速度仍比VC快好几倍。并不是说微软的编译器不行,这是由C++的复杂性决定的。模板的处理、预处理和宏的展开都是很费时的。前文不是提到Object Pascal没有模板、预处理和宏吗?这本来是缺点,但带来的一个好处就是编译速度极快。至于编译完的二进制代码,在打开相同的优化选项的情况下,Delphi和VC执行速度并没有太大的差别。
为了克服编译的速度问题,C++编译器一般需要增强的连接器和预处理机制。但是预处理机制仍然存在若干问题:1)程序调试的断点行可能和代码行不同;2)没有将最新的代码信息综合进去;3)容易产生错误的逻辑;4)因为读错文件头而很容易产生类似"Unexpected End of File"的错误。
两个编译器有个共同点是都能识别无用的"死"代码,比如一个没有用的函数等等。编译后的程序将不包含这些多余的信息。Delphi在这方面作得更加出色。它可以让你在编辑器中可视化地提示出那行代码是"活"的、那行代码是"死"的。这样你就能整理出最精简的代码。Delphi在编译后将在左边显示一个小蓝点表示这行代码是"活"的。Visual C++做不到这点。
Delphi编译后可执行文件至少有200K(如果不使用VCL,仅仅使用WinAPI,文件的大小将大大缩小)但是Visual C++编程使用MFC编译后的可执行文件通常只有几十K,主要是因为微软已经将系统运行库包含在Windows系统了(Borland公司曾经和微软协商这个接口,但是微软利用操作系统的优势不愿意公开)。同样道理,使用BDE开发的的数据库程序必须附带3-5M的额外系统文件,也是非常不协调的。
非常有趣的是,Delphi能够使用由C++ Builder创建的的OBJ文件,但是使用上受很大的局限性。
最后,Visual C++的编译和连接时的错误信息比Delphi要详细和具体的多。特别是使用ATL开发更加如此。
应用框架:MFC?有KFC流行吗?
应用程序框架(Application Frame),有时也称为对象框架。Visual C++采用的框架是MFC。MFC不仅仅是人们通常理解的一个类库(同样,Delphi的VCL也不仅仅是一个控件库,尽管它的名字叫"可视控件库")。你如果选择了MFC,也就选择了一种程序结构,一种编程风格。MFC早在Windows 3.x的时代就出现了,那时的Visual C++还是16位的。经过这些年的不断补充和完善,MFC已经十分成熟。但由于原型出现得比较早,MFC相比于VCL落后了一个时代。尽管微软对MFC的更新没有停止,我也经常读到"只要Windows不过时,MFC就不会过时"之类观点的文章,但就象Inprise(原Borland)的OWL框架的淡出一样,MFC的淡出也是早晚的事。其实MFC是和OWL同一个时代的产物。OWL已经不在了,MFC怎能不"居安思危"呢?如果MFC青春永驻,微软的开发人员也不会"私自"开发出基于ATL的WTL呀。当然,WTL的地位不能和MFC比,它并不是微软官方支持的框架,封装的功能也相当有限。但至少也反衬出了MFC存在的不足。
#31
..接上
我们以为,最能体现一个应用程序框架的先进性的是它的委托模型,即对Windows消息的封装机制。对Windows API的封装就不用说了吧。大同小异,也没什么技术含量。如果高兴,你也可以自己写一个类库来封装。但对Windows消息驱动机制的封装就不是那么容易的了。最自然的封装方式是采用虚成员函数。如果要响应某个消息就重载相应的虚函数。但出乎我的意料,MFC采用的是"古老"的宏定义方法。用宏定义方法的好处是省去了虚函数VTable的系统开销(由于Windows的消息种类很多,开销不算太小)。不过带来的缺点就是映射不太直观。对于MFC,则是"太不直观"了。它的消息映射代码虽然是可见的,但"劝君莫碰"。好在VC的ClassWizard可以自动生成消息映射代码,使用起来还算方便。但和VCL的委托模型相比,MFC的映射方法就显得太落后了。而Delphi的Object Pascal因为没有"标准负担",语言引入了组件、事件处理、属性等新特性。由于功夫做在编译器级,生成的源代码就显得十分简洁。似乎VC是"让框架迁就语言",而Delphi是"让语言迁就框架"。
我想举一个对字符串操作的封装的例子来说明MFC和VCL的优缺点。在MFC中,CStringList类有加入、获取、删除等功能,但VCL的TStringList类除了上述功能还有排序、从逗号分隔的字串读入、流输入输出等功能。但同样的字符串替换功能,VCL的StringReplace要比MFC的CString::Replace慢2-3倍。总的来说,VCL的封装比MFC更为高层,更为抽象,但不可避免地带来的问题是某些部分执行效率比MFC略低。这就象低级语言(如汇编)的执行效率比高级语言(如Basic)高,但编程效率较低。鱼和熊掌不可兼得嘛。
VCL比之MFC的另一优点是对异常处理的支持,而一大缺点是对多线程支持差。VCL的大部分都不是针对多线程优化的。虽说VCL提供了简化多线程操作的类,但只是工作者线程(worker threads)使用起来比较简单。如果线程要和界面打交道的话事情就变得麻烦了,因为除了应用程序的主线程,任何线程不能访问任何可视的VCL部件。你不得不使用Synchronize方法等待主线程处理它的消息,然后在主线程中访问VCL部件。而MFC就没有这样的限制。
稳定性与完善程度:VC是老大哥
VC要比Delphi稳定和完善。VC的发展历史比Delphi长,微软的总体实力比Inprise强。VC的框架MFC经历了那么多年的发展和完善,功能非常全面,而且十分稳定,bug很少。其中你可能遇到的bug也更少。而且有第三方的专门工具帮助你避开这些bug。如此规模的一个类库,能做到这一点不容易。不要小看了这一点,很多专业程序员就是为这个选择VC的。因为尽管VCL比MFC的抽象程度高,封装较为高层,但由此带来的开发效率的提高对高手来说毕竟是有限的。而如果你遇到一个怪问题,调试了半天,发现不是你的代码有错,而是VCL的bug,你作何感想?虽说遇到这类问题的可能性很小,但对VCL的形象的影响可不小。Delphi的IDE太占资源,启动速度太慢,和某些显卡驱动程序冲突,VCL中有bug,调试器不够健壮,对不稳定的第三方控件没有防护措施 …… 问题多多,在这方面Delphi不如VC。希望Inprise能更上一层楼。顺便说一下,我们在网上看到有些人极言Delphi的不稳定,说几分钟出现20多次非法操作。Delphi的确不如Visual C++稳定,但也不至于如此呀。我估计是那位朋友的Delphi装了某些有问题的第三方控件,导致了Delphi的频频出错。不妨卸下那些控件试试?
可移植性:立足现实,放眼未来
Inprise正在开发Delphi的Linux版本,代号为Kylix。也许通过Kylix,用VCL构架编写的Windows程序向Linux移植成为可能。但这只是可能。因为在目前Inprise的兼容性工作做得并不好。低版本的Delphi不能使用高版本的VCL组件,而高版本的Delphi竟然不能使用低版本的VCL组件。真是岂有此理,我们很少看见软件有不向下二进制兼容的。如果Windows 98不能运行95的程序,Windows 95不能运行3.x的程序,Win 3.x不能运行DOS程序,你还会用Windows吗?如果Windows 95的程序必须经过重新编译才能在98下运行,98会卖得那么好吗?"同门兄弟"C++Builder和Delphi也不能互相使用对方的组件,甚至同一套VCL库的文件名也不一样。所以一个组件有for D1/D2/D3/D4/D5/C1/C3/C4/C5这些不同版本是常有的事,而且随着Delphi和C++Builder版本的升级可能还会增加。希望Inprise能先解决同门兄弟的兼容性问题。而微软的VC就没有这类问题。MFC1.0的程序也可以毫无障碍地在VC6.0下编译通过。
集成界面:宏观与微观
就大处说,VC的集成界面是不如Delphi的。Delphi仅仅一个Object Inspector就可以将VC的一堆Wizards比下去,何况它还有Code Explorer、ToDo List等。但从小处,又可以看出Delphi的不成熟。比如"自动完成"功能的智能化程度和提示详细程度不如VC,响应速度也没有VC快。
Visual C++所带的MSDN是一部"开发者的百科全书",信息庞大,查询方便,这方面比Delphi更专业。很多帮助项都有源程序示范。
Delphi的OpenTools是完全面向第三方的开放系统,开发者可以修改很多Borland公司自身的功能,从IDE的可扩充性上说Delphi更好。
调试:细微之处见真功
Visual C++和Delphi的调试功能都非常强大,同时都具有单步可视化调试、断点跟踪、运行时改变变量、鼠标指向可以得到变量值等等功能。对DLL的输入输出也能方便的管理,能够进行源码级别的调试。
相对而言,Visual C++能够更加方便地看到变量的变化情况,这包括对结构可以展开成数据树,从而了解每一个变量的值,每一步调试,变化了的变量会加红,从而使调试更加方便。另外,Visual C++的块内存察看比Delphi也要方便。
当然,Delphi也有很多体贴的细微之处,比如在线程调试的时候,Delphi能够很方便地察看线程的变化,Visual C++却必须要弹出一个模式对话框。
我们以为,最能体现一个应用程序框架的先进性的是它的委托模型,即对Windows消息的封装机制。对Windows API的封装就不用说了吧。大同小异,也没什么技术含量。如果高兴,你也可以自己写一个类库来封装。但对Windows消息驱动机制的封装就不是那么容易的了。最自然的封装方式是采用虚成员函数。如果要响应某个消息就重载相应的虚函数。但出乎我的意料,MFC采用的是"古老"的宏定义方法。用宏定义方法的好处是省去了虚函数VTable的系统开销(由于Windows的消息种类很多,开销不算太小)。不过带来的缺点就是映射不太直观。对于MFC,则是"太不直观"了。它的消息映射代码虽然是可见的,但"劝君莫碰"。好在VC的ClassWizard可以自动生成消息映射代码,使用起来还算方便。但和VCL的委托模型相比,MFC的映射方法就显得太落后了。而Delphi的Object Pascal因为没有"标准负担",语言引入了组件、事件处理、属性等新特性。由于功夫做在编译器级,生成的源代码就显得十分简洁。似乎VC是"让框架迁就语言",而Delphi是"让语言迁就框架"。
我想举一个对字符串操作的封装的例子来说明MFC和VCL的优缺点。在MFC中,CStringList类有加入、获取、删除等功能,但VCL的TStringList类除了上述功能还有排序、从逗号分隔的字串读入、流输入输出等功能。但同样的字符串替换功能,VCL的StringReplace要比MFC的CString::Replace慢2-3倍。总的来说,VCL的封装比MFC更为高层,更为抽象,但不可避免地带来的问题是某些部分执行效率比MFC略低。这就象低级语言(如汇编)的执行效率比高级语言(如Basic)高,但编程效率较低。鱼和熊掌不可兼得嘛。
VCL比之MFC的另一优点是对异常处理的支持,而一大缺点是对多线程支持差。VCL的大部分都不是针对多线程优化的。虽说VCL提供了简化多线程操作的类,但只是工作者线程(worker threads)使用起来比较简单。如果线程要和界面打交道的话事情就变得麻烦了,因为除了应用程序的主线程,任何线程不能访问任何可视的VCL部件。你不得不使用Synchronize方法等待主线程处理它的消息,然后在主线程中访问VCL部件。而MFC就没有这样的限制。
稳定性与完善程度:VC是老大哥
VC要比Delphi稳定和完善。VC的发展历史比Delphi长,微软的总体实力比Inprise强。VC的框架MFC经历了那么多年的发展和完善,功能非常全面,而且十分稳定,bug很少。其中你可能遇到的bug也更少。而且有第三方的专门工具帮助你避开这些bug。如此规模的一个类库,能做到这一点不容易。不要小看了这一点,很多专业程序员就是为这个选择VC的。因为尽管VCL比MFC的抽象程度高,封装较为高层,但由此带来的开发效率的提高对高手来说毕竟是有限的。而如果你遇到一个怪问题,调试了半天,发现不是你的代码有错,而是VCL的bug,你作何感想?虽说遇到这类问题的可能性很小,但对VCL的形象的影响可不小。Delphi的IDE太占资源,启动速度太慢,和某些显卡驱动程序冲突,VCL中有bug,调试器不够健壮,对不稳定的第三方控件没有防护措施 …… 问题多多,在这方面Delphi不如VC。希望Inprise能更上一层楼。顺便说一下,我们在网上看到有些人极言Delphi的不稳定,说几分钟出现20多次非法操作。Delphi的确不如Visual C++稳定,但也不至于如此呀。我估计是那位朋友的Delphi装了某些有问题的第三方控件,导致了Delphi的频频出错。不妨卸下那些控件试试?
可移植性:立足现实,放眼未来
Inprise正在开发Delphi的Linux版本,代号为Kylix。也许通过Kylix,用VCL构架编写的Windows程序向Linux移植成为可能。但这只是可能。因为在目前Inprise的兼容性工作做得并不好。低版本的Delphi不能使用高版本的VCL组件,而高版本的Delphi竟然不能使用低版本的VCL组件。真是岂有此理,我们很少看见软件有不向下二进制兼容的。如果Windows 98不能运行95的程序,Windows 95不能运行3.x的程序,Win 3.x不能运行DOS程序,你还会用Windows吗?如果Windows 95的程序必须经过重新编译才能在98下运行,98会卖得那么好吗?"同门兄弟"C++Builder和Delphi也不能互相使用对方的组件,甚至同一套VCL库的文件名也不一样。所以一个组件有for D1/D2/D3/D4/D5/C1/C3/C4/C5这些不同版本是常有的事,而且随着Delphi和C++Builder版本的升级可能还会增加。希望Inprise能先解决同门兄弟的兼容性问题。而微软的VC就没有这类问题。MFC1.0的程序也可以毫无障碍地在VC6.0下编译通过。
集成界面:宏观与微观
就大处说,VC的集成界面是不如Delphi的。Delphi仅仅一个Object Inspector就可以将VC的一堆Wizards比下去,何况它还有Code Explorer、ToDo List等。但从小处,又可以看出Delphi的不成熟。比如"自动完成"功能的智能化程度和提示详细程度不如VC,响应速度也没有VC快。
Visual C++所带的MSDN是一部"开发者的百科全书",信息庞大,查询方便,这方面比Delphi更专业。很多帮助项都有源程序示范。
Delphi的OpenTools是完全面向第三方的开放系统,开发者可以修改很多Borland公司自身的功能,从IDE的可扩充性上说Delphi更好。
调试:细微之处见真功
Visual C++和Delphi的调试功能都非常强大,同时都具有单步可视化调试、断点跟踪、运行时改变变量、鼠标指向可以得到变量值等等功能。对DLL的输入输出也能方便的管理,能够进行源码级别的调试。
相对而言,Visual C++能够更加方便地看到变量的变化情况,这包括对结构可以展开成数据树,从而了解每一个变量的值,每一步调试,变化了的变量会加红,从而使调试更加方便。另外,Visual C++的块内存察看比Delphi也要方便。
当然,Delphi也有很多体贴的细微之处,比如在线程调试的时候,Delphi能够很方便地察看线程的变化,Visual C++却必须要弹出一个模式对话框。
#32
..接上
数据库开发:Delphi一枝独秀
数据库支持是Delphi的强项。这主要体现在Delphi与BDE的无缝集成,以及Delphi提供的那一大堆现成的数据库操作控件。这是VC望尘莫及的。目前Delphi支持BDE、ADO、InterBase三种数据库访问方式。所有的方式都能拖拉到应用程序中实现可视化操作。正是因为Delphi对数据库类的包装,使得用户操作数据库不像在Visual C++中必须从开始到最后都要干预。明显地提高了开发速度。
Delphi中使用WebBroker控件还能很方便地构造出基于数据库的Web页面,通过HTML管理Web数据库。 Visual C++访问数据主要通过ADO和OLEDB,很多ActiveX控件也能添加数据库功能。但是没有像Paradox这样的桌面数据库,Access相对功能太弱了。也许SQL Server是不错的选择。
COM:新技术的力量
COM是组件对象模型的缩写。它是OLE和ActiveX技术的基础,COM定义了一组API和一个二进制标准,让不同的编程语言、不同平台的彼此独立的对象相互进行通讯。
COM是Microsoft制订的行业标准。但Delphi也为COM提供了强大的语言支持。支持接口、variant、宽字符串功能。这些对COM的封装确实比C++更方便。比如在C++(没有类框架)进行COM编程时,变体定义为oaidl.h文件中的VARIANT结构。要处理变体,必须手工调整oleaut32.dll中VariantXXXX() API函数对其进行初始化和管理,如VariantInit()、VariantCopy()、VariantClear()等等。
Visual C++实现COM编程有一种特殊的方法就是使用ATL。ATL使用Visual C++特有的多重继承来实现COM接口。虽然不见得实现COM服务和控制更容易,但是ATL和最新COM技术的接口,基于模板的构造都比Delphi强。ATL更有利于建立小巧、快捷的COM组件程序。
按目前通用的观点,Visual C++应用到COM服务程序更有优势,Delphi应用到COM组件程序更合适。
昨天,今天,明天
技术的进步在很多时候是此消彼长的。当初Borland的Turbo C和Borland C++几乎是C/C++程序员唯一的选择。微软的Quick C(现在还有人知道这个产品吗?)和Microsoft C/C++从来也没有成为过主流。但Borland C++又流行了多少年呢?不久就被新崛起的Microsoft Visual C/C++压下去了。于是Inprise(原Borland)拣起了当年Turbo Pascal和Borland Pascal的辉煌(事实上Borland的成名作就是第一个Pascal编译器),全力推出了Delphi。Delphi当初推出时被称为VB杀手,但VB现在仍然活得挺好。毕竟微软是靠Basic起家的嘛,VB不是那么容易被打败的。Inprise想了想不和VB争了,使用Delphi的IDE和VCL配上C++语言,推出了C++Builder,又向Visual C++的市场发起了夹攻。C++Builder似乎是个不错的折衷选择了?再仔细想想!C++Builder的优点Delphi都有,但Delphi的优点C++Builder未必有。比如C++Builder的编译速度比VC还慢,哪能和Delphi比?而且因为VCL是Object Pascal写的,C++语言和VCL磨合得并不好。C++Builder的bug比Delphi还多,甚至Sample代码中还有错。VCL的部分功能不能使用,要靠嵌入pascal代码访问。C++Builder可用的第三方控件远没有Delphi多。
唉,真是金无足赤。Microsoft和Inprise,谁会笑在最后呢?
鱼和熊掌:艰难的选择
选择一个开发工具依赖于很多不同的因素,每个人都能因为某种语言的某个缺陷而放弃学习或使用这种语言。任何程序员都希望自己喜欢的工具能达到理想的境界,通过上面不完善的比较,我想大家都有自己的看法。我们认为影响大家选择开发语言的因素主要包括:
1) 哪门语言更容易入门?
学习一种语言需要投入大量的时间和精力。开发程序的开发成本是值得考虑的现实。一个熟练的Delphi程序员和一个熟练的VC程序员工作效率是一样的。但是,成为熟练的程序员必须很快掌握一门语言的技巧。不幸的是,目前熟练的Visual C++程序员是十里挑一。相对而言,Delphi更适合初学者。
2) 哪门语言有更多可继承的代码?
语言代码的可重用性是加快开发效率明显方面,从早期的过程、函数到现在的组件技术都是朝这个目标在奋斗。这两种语言对代码重用的理解是不一样的,Delphi主要通过VCL控件来实现代码重用,Visual C++实现起来就比较复杂。
3) 语言自身的本性。
就技术(主要指应用框架)来说,Delphi目前领先于Visual C++。但稳定性和健壮性的不足又让我对Inprise"想说爱你不容易"。而VC尽管发展到今日已十分完善,但MFC框架已是明日黄花了。如果不使用MFC,目前又没有合适的替代品。根据你的需要和实际情况做选择吧。实际上Visual C++和Delphi也不是简单竞争关系。它们在许多领域并不重叠,甚至是互补的。到底怎样取舍,要根据你的项目特性决定。如果你开发系统底层的东西,需要极好的兼容性和稳定性,选Visual C++吧。你可以只调用Windows的各种API,不用MFC。如果你写传统的Windows桌面应用程序,Visual C++的MFC框架是"正统"的选择;如果界面部分占这个应用程序代码比例较大的话,或者Delphi中有相关功能的控件的话,Delphi是事半功倍的选择。如果你为企业开发数据库、信息管理系统等高层应用("高层"是相对于"低层/底层"而言的,不是说技术高级或低级),而且有比较紧的期限限制,选Delphi比较好。如果你熟悉的语言是Object Pascal,又不打算学复杂的C++,那么Delphi几乎是唯一的选择。传统的观点是:Delphi适合编写Internet/Intranet、表格制图、数据库操作、高级用户界面等等。Visual C++适合编写设备驱动、COM服务程序、科学计算、控制台(console)程序、WinCE的应用和一些小的工具等等。应用范围的不同要求好的程序员同时精通这两门语言。
4) 语言的前景和可扩充性。
Delphi是Inprise的旗舰产品之一,前景应当还是比较乐观的,而且Inprise已经在向Linux进军了,而微软还迟迟没有动作。遗憾的是,Inprise公司Delphi的创始人已经跳槽到微软去主持Visual J++和C#项目了。但愿对Inprise冲击不会太大。
微软的Visual C++的前景又怎样呢?Visual Studio 7.0就要推出了。这一版本将加强网络开发的特性。看来微软虽然被判解体,开发实力可是一点没打折扣。
另外,虽说MFC已稍显落后,但不是说它不值得学。事实上,不学MFC就等于没学VC。利用MFC框架开发程序仍然是目前开发桌面应用的主流模式,而且还会保持相当长的时间。微软公司CEO史蒂夫·巴尔默(Steve Ballmer)曾说,.NET流行还得等2-3年。那么,MFC至少还有2-3年的生命空间。在技术日新月异的IT界,2-3年实在是很长一段时间了。好好把握吧。即使你不使用MFC框架,花点时间看一下MFC的封装机制对你熟悉C++的OOP机制和Windows底层功能也是很有好处的。而VCL的源代码是Object Pascal的,对C/C++程序员就没有这个"额外"的作用了。
参考文献:
Programming Microsoft Visual C++, 5th Edition, by Scot Wingo & George Shepherd
MSDN, by Microsoft Corp.
Visual C++ versus Delphi, by John M. Jacobson BorlandC++Builder3Unleashed,byCharlieCalvert,etal.
Borland Delphi 5-Developer's Guide,by Inprise Corp.
<<完>>
数据库开发:Delphi一枝独秀
数据库支持是Delphi的强项。这主要体现在Delphi与BDE的无缝集成,以及Delphi提供的那一大堆现成的数据库操作控件。这是VC望尘莫及的。目前Delphi支持BDE、ADO、InterBase三种数据库访问方式。所有的方式都能拖拉到应用程序中实现可视化操作。正是因为Delphi对数据库类的包装,使得用户操作数据库不像在Visual C++中必须从开始到最后都要干预。明显地提高了开发速度。
Delphi中使用WebBroker控件还能很方便地构造出基于数据库的Web页面,通过HTML管理Web数据库。 Visual C++访问数据主要通过ADO和OLEDB,很多ActiveX控件也能添加数据库功能。但是没有像Paradox这样的桌面数据库,Access相对功能太弱了。也许SQL Server是不错的选择。
COM:新技术的力量
COM是组件对象模型的缩写。它是OLE和ActiveX技术的基础,COM定义了一组API和一个二进制标准,让不同的编程语言、不同平台的彼此独立的对象相互进行通讯。
COM是Microsoft制订的行业标准。但Delphi也为COM提供了强大的语言支持。支持接口、variant、宽字符串功能。这些对COM的封装确实比C++更方便。比如在C++(没有类框架)进行COM编程时,变体定义为oaidl.h文件中的VARIANT结构。要处理变体,必须手工调整oleaut32.dll中VariantXXXX() API函数对其进行初始化和管理,如VariantInit()、VariantCopy()、VariantClear()等等。
Visual C++实现COM编程有一种特殊的方法就是使用ATL。ATL使用Visual C++特有的多重继承来实现COM接口。虽然不见得实现COM服务和控制更容易,但是ATL和最新COM技术的接口,基于模板的构造都比Delphi强。ATL更有利于建立小巧、快捷的COM组件程序。
按目前通用的观点,Visual C++应用到COM服务程序更有优势,Delphi应用到COM组件程序更合适。
昨天,今天,明天
技术的进步在很多时候是此消彼长的。当初Borland的Turbo C和Borland C++几乎是C/C++程序员唯一的选择。微软的Quick C(现在还有人知道这个产品吗?)和Microsoft C/C++从来也没有成为过主流。但Borland C++又流行了多少年呢?不久就被新崛起的Microsoft Visual C/C++压下去了。于是Inprise(原Borland)拣起了当年Turbo Pascal和Borland Pascal的辉煌(事实上Borland的成名作就是第一个Pascal编译器),全力推出了Delphi。Delphi当初推出时被称为VB杀手,但VB现在仍然活得挺好。毕竟微软是靠Basic起家的嘛,VB不是那么容易被打败的。Inprise想了想不和VB争了,使用Delphi的IDE和VCL配上C++语言,推出了C++Builder,又向Visual C++的市场发起了夹攻。C++Builder似乎是个不错的折衷选择了?再仔细想想!C++Builder的优点Delphi都有,但Delphi的优点C++Builder未必有。比如C++Builder的编译速度比VC还慢,哪能和Delphi比?而且因为VCL是Object Pascal写的,C++语言和VCL磨合得并不好。C++Builder的bug比Delphi还多,甚至Sample代码中还有错。VCL的部分功能不能使用,要靠嵌入pascal代码访问。C++Builder可用的第三方控件远没有Delphi多。
唉,真是金无足赤。Microsoft和Inprise,谁会笑在最后呢?
鱼和熊掌:艰难的选择
选择一个开发工具依赖于很多不同的因素,每个人都能因为某种语言的某个缺陷而放弃学习或使用这种语言。任何程序员都希望自己喜欢的工具能达到理想的境界,通过上面不完善的比较,我想大家都有自己的看法。我们认为影响大家选择开发语言的因素主要包括:
1) 哪门语言更容易入门?
学习一种语言需要投入大量的时间和精力。开发程序的开发成本是值得考虑的现实。一个熟练的Delphi程序员和一个熟练的VC程序员工作效率是一样的。但是,成为熟练的程序员必须很快掌握一门语言的技巧。不幸的是,目前熟练的Visual C++程序员是十里挑一。相对而言,Delphi更适合初学者。
2) 哪门语言有更多可继承的代码?
语言代码的可重用性是加快开发效率明显方面,从早期的过程、函数到现在的组件技术都是朝这个目标在奋斗。这两种语言对代码重用的理解是不一样的,Delphi主要通过VCL控件来实现代码重用,Visual C++实现起来就比较复杂。
3) 语言自身的本性。
就技术(主要指应用框架)来说,Delphi目前领先于Visual C++。但稳定性和健壮性的不足又让我对Inprise"想说爱你不容易"。而VC尽管发展到今日已十分完善,但MFC框架已是明日黄花了。如果不使用MFC,目前又没有合适的替代品。根据你的需要和实际情况做选择吧。实际上Visual C++和Delphi也不是简单竞争关系。它们在许多领域并不重叠,甚至是互补的。到底怎样取舍,要根据你的项目特性决定。如果你开发系统底层的东西,需要极好的兼容性和稳定性,选Visual C++吧。你可以只调用Windows的各种API,不用MFC。如果你写传统的Windows桌面应用程序,Visual C++的MFC框架是"正统"的选择;如果界面部分占这个应用程序代码比例较大的话,或者Delphi中有相关功能的控件的话,Delphi是事半功倍的选择。如果你为企业开发数据库、信息管理系统等高层应用("高层"是相对于"低层/底层"而言的,不是说技术高级或低级),而且有比较紧的期限限制,选Delphi比较好。如果你熟悉的语言是Object Pascal,又不打算学复杂的C++,那么Delphi几乎是唯一的选择。传统的观点是:Delphi适合编写Internet/Intranet、表格制图、数据库操作、高级用户界面等等。Visual C++适合编写设备驱动、COM服务程序、科学计算、控制台(console)程序、WinCE的应用和一些小的工具等等。应用范围的不同要求好的程序员同时精通这两门语言。
4) 语言的前景和可扩充性。
Delphi是Inprise的旗舰产品之一,前景应当还是比较乐观的,而且Inprise已经在向Linux进军了,而微软还迟迟没有动作。遗憾的是,Inprise公司Delphi的创始人已经跳槽到微软去主持Visual J++和C#项目了。但愿对Inprise冲击不会太大。
微软的Visual C++的前景又怎样呢?Visual Studio 7.0就要推出了。这一版本将加强网络开发的特性。看来微软虽然被判解体,开发实力可是一点没打折扣。
另外,虽说MFC已稍显落后,但不是说它不值得学。事实上,不学MFC就等于没学VC。利用MFC框架开发程序仍然是目前开发桌面应用的主流模式,而且还会保持相当长的时间。微软公司CEO史蒂夫·巴尔默(Steve Ballmer)曾说,.NET流行还得等2-3年。那么,MFC至少还有2-3年的生命空间。在技术日新月异的IT界,2-3年实在是很长一段时间了。好好把握吧。即使你不使用MFC框架,花点时间看一下MFC的封装机制对你熟悉C++的OOP机制和Windows底层功能也是很有好处的。而VCL的源代码是Object Pascal的,对C/C++程序员就没有这个"额外"的作用了。
参考文献:
Programming Microsoft Visual C++, 5th Edition, by Scot Wingo & George Shepherd
MSDN, by Microsoft Corp.
Visual C++ versus Delphi, by John M. Jacobson BorlandC++Builder3Unleashed,byCharlieCalvert,etal.
Borland Delphi 5-Developer's Guide,by Inprise Corp.
<<完>>
#33
这篇文章看内容应该很老,不过我没有看过,有些地方不太同意,在这里列出来供大家参考:
>……但VCL的TStringList类除了上述功能还有排序、从逗号分隔的字串读入、流输入输出等功
>能。……
CStringList实现了迭代器模式,这是一种算法与数据结构相分离的模式,当然不会再把排序等算法放到容器中。事实上我如果为它写一个简单的适配器就可以使用stl中的所有算法,包括排序、二分查找、并配合i(o)stream_iterator实现流输入输出,还可以使用很多其它算法TStringList中没有的其它算法。字符串分割的算法stl中没有,但如果你写了一个,它将不只可以用于CStringList,还可以用于std::vector<std::string>,std::vector<CString>,std::list<std::string>,std::list<CString>……这是一种成熟的模式而不是缺陷。反观VCL,TStringList中有一个Sort,TList中也有一个Sort,但如果我要对一个TCollection中的元素进行排序呢?好象都用不上。如果某一天我写了一个新的容器,还要自已为它实现一个Sort……
>Delphi的OpenTools是完全面向第三方的开放系统,开发者可以修改很多Borland公司自身的功能,
>从IDE的可扩充性上说Delphi更好。
我个人比较喜欢Delphi/BCB的IDE,但关于可扩充性上我要为VC说一句公道话。虽然Delphi/BCB的OpenTools灵活强大,几乎什么都可以做(包括写一个病毒),但使用起来不是很容易;而VC中的宏相比之下很简单好用,很多在VC中很容易写的宏在Delphi中要写一大段代码来实现,而这些扩充其实是很常见的。一个功能强大,一个简单好用,两个相比不能说谁强过了谁。如果把两种方法结合起来——简单的事情由宏实现,复杂的问题写复杂的代码——这样会用起来更方便。
>即使你不使用MFC框架,花点时间看一下MFC的封装机制对你熟悉C++的OOP机制和Windows底层功能也
>是很有好处的。
熟悉Windows底层是有的,但MFC并不代表C++的OOP机制。事实上,在GUI方面,MFC可以说只是对Windows API的最简单的封装,几乎每一个方法都可以在Windows API中找到对应版本——只是少了个Handle参数,并且到处都能看到Windows消息出现。MFC中比较值得一提的是内置的文档—视图模式(MVC模式的一个变种)和对永久化的支持,不过文档—视图模式在遇到不需要这种模式的应用时反而增加了复杂度,在VC5中这一点尤其明显,不过在VC6中这一模式成为可选项了。VC中的永久化初上手用的时候很方便,但更多时候我们需要严格控制文件格式,这时它的帮助就不大的;并且它的实现还忽略了一个永久化时应该处理的重要问题——字节序问题。
事实上MFC应该说是一个成功的Windows下的GUI框架,但不能说它是一个优秀的框架,与QT或是wxWindows相比差得很远,即使是MS的工程师也承认:“MFC其实是一个失败的作品。”但由于各种原因(比较兼容旧版本),MFC很难作出什么改动。MS恐怕也没有想过再对它进行改动,在多年前就已经开始酝酿.Net了,最终目标就是让大家转到.Net框架上,这样对MFC动大手术就成了没有必要的举动。
>C++Builder似乎是个不错的折衷选择了?再仔细想想!C++Builder的优点Delphi都有,但Delphi的
>优点C++Builder未必有。比如C++Builder的编译速度比VC还慢,哪能和Delphi比?
我可不这样想,BCB一直是我比较喜欢的开发工具,如果它的编译优化实现得再好一些就是我最喜欢的了。与用Delphi相比,BCB并非是有破坏无建设,在BCB中,我可以使用STL容器和算法(VCL在这方面做得还不够),还可以使用boost、loki等第三方库的能力,并把这些都和VCL对象结合在一起使用,非常方便。我可以使用RAII来处理异常,用scoped_lock来加锁和解锁,不用再在代码中写丑陋的try-finally。可能最大的缺点就是没有message handler方法,不得不用多分支语句来完成Windows消息的分派(不要去看那些丑陋的宏,其实就是switch、case、default)——和MFC学的,不过这些只是在你需要自己处理Windows消息时才用到,由于VCL的优秀封装,这种情况并不常见。
>COM是Microsoft制订的行业标准。但Delphi也为COM提供了强大的语言支持。支持接口、variant、
>宽字符串功能。这些对COM的封装确实比C++更方便。
C/C++最重要的思想就是“语言没有能力,由库来实现”,不使用框架如果是指不使用任何程序库的话,那你还能用C/C++做什么?Delphi中内置支持确实不错,但我在VC中用_com_ptr_t、variant_t、bstr_t也并没有感到不方便。注意这些类并不是ATL或是MFC的内容,它们是独立存在的。在这里C++体现了它强大的类型扩充能力,有什么不满意的还可以再扩充。而Object Pascal由于没有这种能力(需要值对象+自定义操作符+模板),只能由语言支持,但支持得不好的情况你也只能忍受。在D6中在Variant中存放无符号整数有问题:它用_VarToInt来转换到无符号整数,虽然D5中也是这样做的,但D6中这个单元加进了整数溢出检查,结果只能有一半的无符号整数放到Variant中并成功取出来。WordBool放到Variant也有问题:当内容是true时,它会转换为bool的true,然后这个值会直接返回,这是一个整数1,而WordBool的逻辑是true是-1,结果判断为假。这两个问题都是我在项目中遇到的。还有前一段时间遇到主要时间花费在OleVaraint的释放上——1w个左右要180秒,我改用内部类型存储后只要1xx毫秒,不知道是COM的问题还是Object Pascal的问题。
还有无观紧要的一点:Borland的成名作应该是SK而不是Turbo Pascal,SK在Turbo Pascal之前就取得了成功,它的用户远比Turbo Pascal的用户多——尽管它是防拷贝的而Turbo Pascal没有。记得当年学习汇编时我就是用SK进行源代码编辑(当然,是D版的)。Turbo Pascal是一个里程碑式的产品,但它对Borland的重要性远比不上它对Pascal的重要性。Turbo C的成功才是Borland的开发工具上的里程碑,而这一成功其实是Turbo Debuger带来的——尽管TC的“一次扫描编译”听上去很让人激动。后来到了BC系列,Borland的IDE和工具才真正体现出优点来,尤其是Resouse WorkShop,它的出现让程序员不再需要在坐标纸上描对话框,可以说是最早的成功的“可视化编程”概念——RC文件也是程序,不是吗?
>……但VCL的TStringList类除了上述功能还有排序、从逗号分隔的字串读入、流输入输出等功
>能。……
CStringList实现了迭代器模式,这是一种算法与数据结构相分离的模式,当然不会再把排序等算法放到容器中。事实上我如果为它写一个简单的适配器就可以使用stl中的所有算法,包括排序、二分查找、并配合i(o)stream_iterator实现流输入输出,还可以使用很多其它算法TStringList中没有的其它算法。字符串分割的算法stl中没有,但如果你写了一个,它将不只可以用于CStringList,还可以用于std::vector<std::string>,std::vector<CString>,std::list<std::string>,std::list<CString>……这是一种成熟的模式而不是缺陷。反观VCL,TStringList中有一个Sort,TList中也有一个Sort,但如果我要对一个TCollection中的元素进行排序呢?好象都用不上。如果某一天我写了一个新的容器,还要自已为它实现一个Sort……
>Delphi的OpenTools是完全面向第三方的开放系统,开发者可以修改很多Borland公司自身的功能,
>从IDE的可扩充性上说Delphi更好。
我个人比较喜欢Delphi/BCB的IDE,但关于可扩充性上我要为VC说一句公道话。虽然Delphi/BCB的OpenTools灵活强大,几乎什么都可以做(包括写一个病毒),但使用起来不是很容易;而VC中的宏相比之下很简单好用,很多在VC中很容易写的宏在Delphi中要写一大段代码来实现,而这些扩充其实是很常见的。一个功能强大,一个简单好用,两个相比不能说谁强过了谁。如果把两种方法结合起来——简单的事情由宏实现,复杂的问题写复杂的代码——这样会用起来更方便。
>即使你不使用MFC框架,花点时间看一下MFC的封装机制对你熟悉C++的OOP机制和Windows底层功能也
>是很有好处的。
熟悉Windows底层是有的,但MFC并不代表C++的OOP机制。事实上,在GUI方面,MFC可以说只是对Windows API的最简单的封装,几乎每一个方法都可以在Windows API中找到对应版本——只是少了个Handle参数,并且到处都能看到Windows消息出现。MFC中比较值得一提的是内置的文档—视图模式(MVC模式的一个变种)和对永久化的支持,不过文档—视图模式在遇到不需要这种模式的应用时反而增加了复杂度,在VC5中这一点尤其明显,不过在VC6中这一模式成为可选项了。VC中的永久化初上手用的时候很方便,但更多时候我们需要严格控制文件格式,这时它的帮助就不大的;并且它的实现还忽略了一个永久化时应该处理的重要问题——字节序问题。
事实上MFC应该说是一个成功的Windows下的GUI框架,但不能说它是一个优秀的框架,与QT或是wxWindows相比差得很远,即使是MS的工程师也承认:“MFC其实是一个失败的作品。”但由于各种原因(比较兼容旧版本),MFC很难作出什么改动。MS恐怕也没有想过再对它进行改动,在多年前就已经开始酝酿.Net了,最终目标就是让大家转到.Net框架上,这样对MFC动大手术就成了没有必要的举动。
>C++Builder似乎是个不错的折衷选择了?再仔细想想!C++Builder的优点Delphi都有,但Delphi的
>优点C++Builder未必有。比如C++Builder的编译速度比VC还慢,哪能和Delphi比?
我可不这样想,BCB一直是我比较喜欢的开发工具,如果它的编译优化实现得再好一些就是我最喜欢的了。与用Delphi相比,BCB并非是有破坏无建设,在BCB中,我可以使用STL容器和算法(VCL在这方面做得还不够),还可以使用boost、loki等第三方库的能力,并把这些都和VCL对象结合在一起使用,非常方便。我可以使用RAII来处理异常,用scoped_lock来加锁和解锁,不用再在代码中写丑陋的try-finally。可能最大的缺点就是没有message handler方法,不得不用多分支语句来完成Windows消息的分派(不要去看那些丑陋的宏,其实就是switch、case、default)——和MFC学的,不过这些只是在你需要自己处理Windows消息时才用到,由于VCL的优秀封装,这种情况并不常见。
>COM是Microsoft制订的行业标准。但Delphi也为COM提供了强大的语言支持。支持接口、variant、
>宽字符串功能。这些对COM的封装确实比C++更方便。
C/C++最重要的思想就是“语言没有能力,由库来实现”,不使用框架如果是指不使用任何程序库的话,那你还能用C/C++做什么?Delphi中内置支持确实不错,但我在VC中用_com_ptr_t、variant_t、bstr_t也并没有感到不方便。注意这些类并不是ATL或是MFC的内容,它们是独立存在的。在这里C++体现了它强大的类型扩充能力,有什么不满意的还可以再扩充。而Object Pascal由于没有这种能力(需要值对象+自定义操作符+模板),只能由语言支持,但支持得不好的情况你也只能忍受。在D6中在Variant中存放无符号整数有问题:它用_VarToInt来转换到无符号整数,虽然D5中也是这样做的,但D6中这个单元加进了整数溢出检查,结果只能有一半的无符号整数放到Variant中并成功取出来。WordBool放到Variant也有问题:当内容是true时,它会转换为bool的true,然后这个值会直接返回,这是一个整数1,而WordBool的逻辑是true是-1,结果判断为假。这两个问题都是我在项目中遇到的。还有前一段时间遇到主要时间花费在OleVaraint的释放上——1w个左右要180秒,我改用内部类型存储后只要1xx毫秒,不知道是COM的问题还是Object Pascal的问题。
还有无观紧要的一点:Borland的成名作应该是SK而不是Turbo Pascal,SK在Turbo Pascal之前就取得了成功,它的用户远比Turbo Pascal的用户多——尽管它是防拷贝的而Turbo Pascal没有。记得当年学习汇编时我就是用SK进行源代码编辑(当然,是D版的)。Turbo Pascal是一个里程碑式的产品,但它对Borland的重要性远比不上它对Pascal的重要性。Turbo C的成功才是Borland的开发工具上的里程碑,而这一成功其实是Turbo Debuger带来的——尽管TC的“一次扫描编译”听上去很让人激动。后来到了BC系列,Borland的IDE和工具才真正体现出优点来,尤其是Resouse WorkShop,它的出现让程序员不再需要在坐标纸上描对话框,可以说是最早的成功的“可视化编程”概念——RC文件也是程序,不是吗?
#34
说的好,顶
#35
称为BORLAND为Inprise的文章一般已经有些旧了。因为当BORLAND更名为INPRISE时,是它最糟糕的时候,也就是DELPHI4的时代,幸好BORLAND后来挺过来了。
#36
汗,插不上嘴
#37
我觉得Object Pascal要求显式指明override是很不错的设计————同意
Object Pascal的析构函数可以不override,不太合理————基本同意(在你不确定的情况下,还是override一下,然后在里面inherited一下)
在C++中如果基类的析构函数是虚的,衍生类的析构也必然是虚的并且是一个override————同意(因为C++的析构函数只能有一个,它会自动调用,如果多个,编译器怎么自动判断呢?不象构造函数,可以给参数什么的来判断的。)
我一直不明白多个析构函数有什么用————同意(我也不太明白,:),或许是因为OP的析构函数要自己调用,所以用户可以自己选择吧。但是为什么要多个呢?为什么呢?有这个必要吗?)
C++中构造和析构函数对基类构造和析构函数的调用是强制性的,其中析构函数是自动调用,构造函数中的指定调用,不指定则调用缺省构造,没有缺省构造则编译出错。而OP中构造和析构函数都可以不调用基类中的相关函数,容易出现Bug。————不同意(不同意你的看法,当然你说的现象是存在的,“C++中构造和析构函数对基类构造和析构函数的调用是强制性的”,因为C++的对象默认是建立在栈上的,生命周期确定,所以什么时候调用构造和析构函数的时间是确定的,而OP则不然。如果C++的对象通过NEW在堆上建立,那创建的时间也是确定的,析构也是确定的,DELETE的时候就调用喽,但是OP又不是。所以OP中的处理方法是你用户自己去决定什么时候构造类对象和析构它。‘而OP中构造和析构函数都可以不调用基类中的相关函数,容易出现Bug’,为什么不调用呢?你不管三七二十一,你inherited一下总归不会出错吧,可以不inherited是因为OP的析构函数是用户自己调用的,所以可以有多个,所以可能基类中没有这个析构函数,所以你可以不inherited,但是这不是你不inherited的原因)
OP中有抽象方法的类也可以创建,只有当某一天代码调用到了这个抽象方法时才会出错;而C++中有未override的纯虚函数的类是不允许实例化的,这一点我更喜欢C++的处理。————(对这一点,我理解不深,不敢评论)
说的不对,请大家批评。
偶是脆鸟。
:)
Object Pascal的析构函数可以不override,不太合理————基本同意(在你不确定的情况下,还是override一下,然后在里面inherited一下)
在C++中如果基类的析构函数是虚的,衍生类的析构也必然是虚的并且是一个override————同意(因为C++的析构函数只能有一个,它会自动调用,如果多个,编译器怎么自动判断呢?不象构造函数,可以给参数什么的来判断的。)
我一直不明白多个析构函数有什么用————同意(我也不太明白,:),或许是因为OP的析构函数要自己调用,所以用户可以自己选择吧。但是为什么要多个呢?为什么呢?有这个必要吗?)
C++中构造和析构函数对基类构造和析构函数的调用是强制性的,其中析构函数是自动调用,构造函数中的指定调用,不指定则调用缺省构造,没有缺省构造则编译出错。而OP中构造和析构函数都可以不调用基类中的相关函数,容易出现Bug。————不同意(不同意你的看法,当然你说的现象是存在的,“C++中构造和析构函数对基类构造和析构函数的调用是强制性的”,因为C++的对象默认是建立在栈上的,生命周期确定,所以什么时候调用构造和析构函数的时间是确定的,而OP则不然。如果C++的对象通过NEW在堆上建立,那创建的时间也是确定的,析构也是确定的,DELETE的时候就调用喽,但是OP又不是。所以OP中的处理方法是你用户自己去决定什么时候构造类对象和析构它。‘而OP中构造和析构函数都可以不调用基类中的相关函数,容易出现Bug’,为什么不调用呢?你不管三七二十一,你inherited一下总归不会出错吧,可以不inherited是因为OP的析构函数是用户自己调用的,所以可以有多个,所以可能基类中没有这个析构函数,所以你可以不inherited,但是这不是你不inherited的原因)
OP中有抽象方法的类也可以创建,只有当某一天代码调用到了这个抽象方法时才会出错;而C++中有未override的纯虚函数的类是不允许实例化的,这一点我更喜欢C++的处理。————(对这一点,我理解不深,不敢评论)
说的不对,请大家批评。
偶是脆鸟。
:)
#38
我觉得Object Pascal要求显式指明override是很不错的设计————同意
Object Pascal的析构函数可以不override,不太合理————基本同意(在你不确定的情况下,还是override一下,然后在里面inherited一下)
在C++中如果基类的析构函数是虚的,衍生类的析构也必然是虚的并且是一个override————同意(因为C++的析构函数只能有一个,它会自动调用,如果多个,编译器怎么自动判断呢?不象构造函数,可以给参数什么的来判断的。)
我一直不明白多个析构函数有什么用————同意(我也不太明白,:),或许是因为OP的析构函数要自己调用,所以用户可以自己选择吧。但是为什么要多个呢?为什么呢?有这个必要吗?)
C++中构造和析构函数对基类构造和析构函数的调用是强制性的,其中析构函数是自动调用,构造函数中的指定调用,不指定则调用缺省构造,没有缺省构造则编译出错。而OP中构造和析构函数都可以不调用基类中的相关函数,容易出现Bug。————不同意(不同意你的看法,当然你说的现象是存在的,“C++中构造和析构函数对基类构造和析构函数的调用是强制性的”,因为C++的对象默认是建立在栈上的,生命周期确定,所以什么时候调用构造和析构函数的时间是确定的,而OP则不然。如果C++的对象通过NEW在堆上建立,那创建的时间也是确定的,析构也是确定的,DELETE的时候就调用喽,但是OP又不是。所以OP中的处理方法是你用户自己去决定什么时候构造类对象和析构它。‘而OP中构造和析构函数都可以不调用基类中的相关函数,容易出现Bug’,为什么不调用呢?你不管三七二十一,你inherited一下总归不会出错吧,可以不inherited是因为OP的析构函数是用户自己调用的,所以可以有多个,所以可能基类中没有这个析构函数,所以你可以不inherited,但是这不是你不inherited的原因)
OP中有抽象方法的类也可以创建,只有当某一天代码调用到了这个抽象方法时才会出错;而C++中有未override的纯虚函数的类是不允许实例化的,这一点我更喜欢C++的处理。————(对这一点,我理解不深,不敢评论)
说的不对,请大家批评。
偶是脆鸟。
:)
Object Pascal的析构函数可以不override,不太合理————基本同意(在你不确定的情况下,还是override一下,然后在里面inherited一下)
在C++中如果基类的析构函数是虚的,衍生类的析构也必然是虚的并且是一个override————同意(因为C++的析构函数只能有一个,它会自动调用,如果多个,编译器怎么自动判断呢?不象构造函数,可以给参数什么的来判断的。)
我一直不明白多个析构函数有什么用————同意(我也不太明白,:),或许是因为OP的析构函数要自己调用,所以用户可以自己选择吧。但是为什么要多个呢?为什么呢?有这个必要吗?)
C++中构造和析构函数对基类构造和析构函数的调用是强制性的,其中析构函数是自动调用,构造函数中的指定调用,不指定则调用缺省构造,没有缺省构造则编译出错。而OP中构造和析构函数都可以不调用基类中的相关函数,容易出现Bug。————不同意(不同意你的看法,当然你说的现象是存在的,“C++中构造和析构函数对基类构造和析构函数的调用是强制性的”,因为C++的对象默认是建立在栈上的,生命周期确定,所以什么时候调用构造和析构函数的时间是确定的,而OP则不然。如果C++的对象通过NEW在堆上建立,那创建的时间也是确定的,析构也是确定的,DELETE的时候就调用喽,但是OP又不是。所以OP中的处理方法是你用户自己去决定什么时候构造类对象和析构它。‘而OP中构造和析构函数都可以不调用基类中的相关函数,容易出现Bug’,为什么不调用呢?你不管三七二十一,你inherited一下总归不会出错吧,可以不inherited是因为OP的析构函数是用户自己调用的,所以可以有多个,所以可能基类中没有这个析构函数,所以你可以不inherited,但是这不是你不inherited的原因)
OP中有抽象方法的类也可以创建,只有当某一天代码调用到了这个抽象方法时才会出错;而C++中有未override的纯虚函数的类是不允许实例化的,这一点我更喜欢C++的处理。————(对这一点,我理解不深,不敢评论)
说的不对,请大家批评。
偶是脆鸟。
:)
#39
晕,怎么发了两次啊?我那些是发给(短歌)的,呵呵.
#40
多谢!再顶。
#41
对API的封装不同.
#42
不错。继续讨论
#43
顶,不错!
#44
MK.
我觉得OO只是面向对象 跟具体的语言是无关的 只不过不同的语言对OO的支持的方法,形式不同而已
对CPP / OP 了解都不是很深 不敢妄言~~~
我觉得OO只是面向对象 跟具体的语言是无关的 只不过不同的语言对OO的支持的方法,形式不同而已
对CPP / OP 了解都不是很深 不敢妄言~~~
#45
回复人: longtusoft(神灯之主) ( ) 信誉:97 2004-10-6 23:07:00 得分: 0
对API的封装不同.
------------
呵呵 不是这样的哦。这里根本就不牵涉到具体的什么API....
对API的封装不同.
------------
呵呵 不是这样的哦。这里根本就不牵涉到具体的什么API....
#46
ding
#47
听课...
#48
大同小异,没什么大区别,
#49
C++和Delphi 都是由结构化语言进化来的OO语言,为了保持与前期语言(C和PASCAL)的兼容性,都存在一些缺陷.
我个人使用C++和DELPHI的感觉来讲,C++的特点之一:灵活性,使它比较难于全面掌握,C++中有太多的特殊情况了;而DELPHI相对简化了很多,比较容易上手.
最近2年少用C++了,对C++有"不满"的同志们可以看看这本书,心情可能会好些,呵呵!
《对象揭秘: Java、Eiffel和C++》 Ian Joyner著 鲍志云 译 人民邮电出版社
我个人使用C++和DELPHI的感觉来讲,C++的特点之一:灵活性,使它比较难于全面掌握,C++中有太多的特殊情况了;而DELPHI相对简化了很多,比较容易上手.
最近2年少用C++了,对C++有"不满"的同志们可以看看这本书,心情可能会好些,呵呵!
《对象揭秘: Java、Eiffel和C++》 Ian Joyner著 鲍志云 译 人民邮电出版社
#50
已阅
^_^
^_^