首先,这仅仅是我个人的观点,仅仅是代表我个人的经历和总结。
为了表明我对
C++的
批判不是人云亦云,首先我说下个人的开发经历,02年开始写linux脚本以及web编程,05开始在正式产品中使用C++一直到现在,其中几个项目用了C语言,C++代码行数为近5万行,C代码近2万行,脚本近2万行。
C++设计目标是提供simula的程序组织能力,同时提供C的效率和灵活。既有执行效率,又能象simula一样提供类、类继承。C++是第一个将基于对象以及OO观念推向开发者的主流语言。所以说C++在某种程度上是成功的,在主流开发者中引入了基于对象、OO、泛型的思想。
C++是一门学院派语言,一门理论化很浓的语言,理论驱动不是实际产品驱动出来的。C++实际上是作者和几个人在一起,“造”出来的模拟simula的C语言,很多的语言特点集合在一起,就成了这个样子,C++是一个天天玩弄语言的人做出来的东西,不实际,不好用。C++妄想一门语言可以完成实际
问题域的建模(类,OO,模板),殊不知实际世界关系是如此的复杂,区区几个语言特征怎么就可以模拟出来?
C++不代表OO:基于对象,也即
数据抽象,关注点是数据表示和行为绑定在一起,即对象的内部构成是怎样的。面向对象OO,关注点是对象间关系及对象的外部接口。
C++提供的类、继承、虚拟函数等只是语言实现OO的手段,并不说明这些就是OO。
面向对象是一种考虑问题的方法,和具体的语言无关,妄图用语言的面向对象来构建问题域的想法出发点就注定了C++这条路并不好走。说的通俗点是把无限的变化投入到语言有限的语法中,小应用还能忍受并且看起来代码还规范很多,大的应用就会让人抓狂。
况且实际应用的模型,千变万化,并不仅仅是基于对象或者面向对象,有些单纯就是算法。
C++不代表泛型:泛型,是一种思想,实际上C++中的template基本就是代码宏在
编译器阶层上的实现而已,
没有新的东西出来,至于函数对象之类,都可以使用函数指针来实现。
C++开发者的思想包袱过重:C++提供过多的选择,也就是说,使用
C++语言解决一个问题,有比较多的语言方案选择,例如继承和泛型都可以实现OO。选择过度,必然过分对比,必然过分疑虑,C++设计者真累。
C++的功能都是通过语言本身来展现的(类,OO,模板),那么要做出一个好的设计(抉择)就必须全部理解上面这些东西才可以,而要理解这些东西,可不是件容易的事情,所以会导致开发者,在做设计的时候,经常反复去查看C++语言资料,这个导致心理包袱过重,担心自己做的不合适。而C++的这些东西学习需要在项目中实践才可以理解,而在项目中实践的话,一开始肯定不是很理解的,所以需要经常性的反复,经常反复后,才真正理解,然后再进一步的理解新的特征,然后在项目中又会使用新的特征,这个过程会让人郁闷、疑惑。我可以肯定说,C++程序员是最郁闷的程序员,根本就没有世界在我手上的感觉。
C++的语言特征,束缚了人的思想,一开始对业务建模,就是分类,然后类继承,这个一点都不符合人的认识规律和实际的业务模型。
C++过多的吸收各类语言特点,至于各个特点是否统一,是否增加用户的思想包袱,这就不管了。
C++语言本身过分设计,将太多的任务放在语言身上了。学习C++导致很多程序员走在一条
错误的面向对象的弯路上,而且浪费了很长很长时间。C++语言本身(设计嵌入在语言中)鼓励和引诱人过分设计,过分使用各类细枝末节的语言
C++过于复杂难以学习:如果语言太复杂,那么无论是教材(教学趋利)或者项目都有使用最新最角落技术的冲动,那么对于使用者和学习者来说,都有很大的心理包袱,因为不是渐进的学习,是一上来就很复杂很陡峭的台阶。如果语言简单,那么就不会对语言的使用产生阻碍。
C++有着过多的教材,一个语言出现那么多的教材,而且很多都是经典,说明想学好这个语言太多困难,需要花费太多的时间。而且很多教材中更多的是炫耀技术和夸大的成分,这点倒和C++语言本身风格一致。在C++很多教材书中,可以看到那些人玩弄语法和triCk,在一个小的圈子中兜来兜去,最后对于实际设计毫无用处。
C++即使学会了也没有用或者不好用:C++的不好,并不仅仅是其难学、花样多,而是其即使学好也很难用,也就是说,即使你什么OO、模板都学得非常熟练,对于业务建模C++也是很难表示的,因为现实世界并不是简单的OO或者模板啊,对于这,你可能又会说,你干嘛要用C++直接建模业务呢,用C啊,但是,请记住,C++一开始其卖点就是OO,也就是可以使用语言特征直接建模啊,所以说,C++的高级语言特征没有实用价值,一个又难学,学会又没有什么用的语言,请简单放弃之。
数据抽象以及类继承真的能否反应真实的现实业务么,或者也就仅仅反应了很小的一个业务范围,更而引申到OO是否真的能够对现实建模有很大的作用,如果这一切的答案都是否定或者不那么肯定的话,其之上建立的细节语法实现有什么意义呢,难道真的就只够给智力高强的学习者以脑力锻炼用么?然后自鸣得意!如果现实软件建模效果有限,那么一个语言中引入那么大复杂度,耗费学习者那么多的精力,根本就不必要。
类继承不符合项目的开发规律,首先,类型树的建立,是建立在对业务的理解上,项目组对业务的理解是逐步深入的,那么在深入理解后,业务模型也就是说类型树要改变,而一开始的代码是建立在父类上的,那么继承关系变了,类的接口也就变了,那么业务相关设计全部都必须修改了,所以类继承不利于项目的进化,不符合人的认知规律。
模板编程,模板编程在很小的范围(单一容器)是有效的,但是真实世界,模板的作用是有限的,很少可以找到真实世界中符合模板的模型特征。
数据抽象是有效的,但是也就仅仅是形式上的有效而已。
对于学会C++的人,常常夸大某个特性的作用,实际上任何语言或者库的特征的作用都是有限的,对于现实项目而言,选择合适的语言,平凡心态去实现它,精心设计、测试、验证更为重要,就像linus说的意思,学会一门难度如C++的语言,并不是什么值得骄傲的事情的,编程语言仅仅是一门语言,并不神秘,即使语言神秘,如果做不出来好用,好维护的软件,那有何用?在一个大的场景中,个别的的特征和语言以及方法论并没有那么重要,这个也包含OO以及设计模式等。
C++的很多语言特征没有用:编译时的
权限控制没有意义,没有让程序员减少负担,没有控制感
构造函数和析构函数自动调用也不好,必须手动调用才让程序员完全控制,因为对象的生存期是个很重要的东西,不能简化,无需作为语言机制,只需成为项目级别的约定
函数定义不放在类中而是放在别的地方,也不好,应该放在类里面。
引入新的操作符new和delete,这两个关键字移植自simula ,new操作符就是在堆内存中分配对象,然后自动调用构造函数而已,这个完全可以采用malloc 加手动函数调用初始化方式来做,无需引入新关键字。
inline无意义,应该完全开放给设计人员,本质上是简单拷贝代码
操作符的重载只是形式上的意义,= 和 set没有本质的区别,仅仅为了形式就去引入新的语法?而且,为了内部类型和用户类型的定义一致就定义赋值重载,也没有意义,内部类型的操作符,其类型和含义是既定的几种而已,用户的那么多类型,也用同样的操作符,根本毫无意义的,例如picture对象,相加有什么意义;运算符和函数本质上是重合的,不符合正交的特点,运算符是一种方便书写的助记符而已。实际的用户类型其接口多样化,根本不是几个操作符可以描叙的。
函数重载其实也没有意义,只是为了减少名字造词的工作,没有本质的提高,一个严肃软件产品怎么会在乎这个小小的工作呢,而且编译后,不还是不同的函数名字么?
默认函数参数:语义错误的来源之一,作为一个强类型检查语言,默认参数就是一个类型检查墙壁上的口子,而且这个还被滥用。
C++成功的产品:寥寥无几,即使有也很快要面对维护者的流失和使用者的离去,例如QT,Boost,ACE等等。
对于QT,我个人并不看好他,构建于C++语言之上就是他的最大的问题,然后就是QT是一门包含基础库和应用库的巨大的库,那么大的库,要维护好,可不容易,加入新的功能而不引入问题(兼容性也算)基本也是个不可能完成的任务。ACE呢,实际项目中用过的都知道,速度太慢、太臃肿。Boost这么多年了,还没有推广开。
项目管理方面的总结:选择一门简约的语言(不那么有野心),使用平凡的心态去学习、使用,精心的设计、编码、测试才是项目的发展的之道。用好一门语言,精心去使用他、体会他,熟悉业务,写出好的软件,比掌握多少语言语法细节都强。
我个人的总结:开发语言转换到C语言,风格切换到C风格,简单的C才是王道,库及工具才是扩展方向。
C语言没有心智包袱,是很简单的一门语言,语言本身几天就可以学习理解完毕。然后就是设计,根据自己的理解做设计进化,这样,在做设计后,不会担自己做的不是最好,即使不是最好,也是在当前的对业务的理解上能做的最好了,这样就不会有心理包袱,而是可以坦然面对进化。
C语言没有束缚人的思想,其本身没有任何业务建模方式,一切都是依靠用户自己建立,所有的一切都可以通过结构、指针、函数来表达,符合实际的业务模型和人的认识规律。
C语言其实并不是什么过程语言,过程语言这个是强加上于他之面的帽子,汇编是过程式的么?一个语言并不是简单的说他是过程,说他处理问题都是过程式的,他也可以以面向对象的方式来实现软件(如果需要面向对象的话),关键是你如何定义面向对象,当然你认为只有C++的面向对象才是面向对象,那就无语了。
[ 此帖被huzhiwen28在2010-11-16 15:04重新编辑 ]