其实严格说来,纯C是门好语言,我很欣赏纯C。但是作为程序设计,C用起来让人觉得很不方便。

  • 在标准C规范中,变量必须在块的头部声明。当然,在近代C编译器中已经取消了这个限制。

  • 我提到过的,C中缺乏高级数据结构支持,导致一些简单问题的实现变得异常复杂。例如我需要解析表达式,生成lisp样子的前缀表达式。这在很多高级语言中是个很简答的事情,但是C中,你不得不自行管理内存和结构,虽然这并不算复杂。

还有一些缺点不能尽述,但是经过时间的考验,C无疑是强大而具有生命力的一种语言。

C++就比较搞笑了,纯C++是一个非常糟糕的东西。我们列举其缺点:

  • 函数指针是C中常用的概念,在C++中应当使用抽象接口-实现的方式,或者使用仿函。从技术上说,在C++中使用函数指针是一个落后而没有C++特色的行为。然而无论使用哪种,生成一个新的函数就必须生成一个新的类。你当自己是java么?

  • 太多internal操作,导致代码隐性错误和思考心智负荷大幅上升。例如某个类可以定义一个单参的构造函数,constructor(int c);这等于定义了一个隐性转换函数,允许将int转换为类。或者使用T operator T();算符函数,将类转换到T。如果此时错误的将类实例当作int来操作,就会产生编译通过但是运行时出错的问题。更严重的是,转换函数严重的消耗性能。在这种情况下,编译和运行都不会出错,只是莫名其妙的性能很差。要避免这个问题,可以用explicit关键字。具体可以看这里(http://www.cnblogs.com/cutepig/archive/2009/01/14/1375917.html)。但是这就需要额外的知识,和随时关心自己是否会犯下这个错误的小心。

  • 强大到啰嗦的模板系统。那位有信心看懂所有stl编译时报错的?反正effactive C++的作者举过一个缺陷,打印了1500个左右的字符。大部分都是符号,望之犹如天书。

  • 为了支持多重继承,导致指针类型转换可能导致指针地址变换。这是一个很扯淡的缺陷,转换指针类型不会引发指针的地址转换是一个C中的基础常识。然而C++为了支持多重继承,导致这个常识被破坏。

  • thiscall和non-thiscall指针无法转换。类成员函数和普通函数指针是无法转换的。这个破坏了所有代码都可获得地址的常识。

其实C++的致命缺陷,就是过度设计。每一步都是很必要很有道理的改进,在最后就组合成了让人望之生畏的复杂系统。

要使用C++,关键就是克制自己的过度设计欲望。C++可以很容易的使用类,模板,友元系统写的很强大,而且看起来很自然。例如你可以定义自己的BioTree,使用+做合并,可以使用|运算符做输出等。然而到最后,就会变成另一种语法。并且,如果合并上大数运算库之类的库,做一个BioTree,其中元素是大数的结构。当这个结构内发生错误的时候,你觉得你能够在里面找到正确的调试方向么?

要克制自己觉得很自然的想法,使用传统C中的一些做法,哪怕他们看起来很古怪,但是这是有道理的。