这个话题历来有很大争议, 喜欢C的对C++不屑一顾,喜欢C++的觉得C是一个子集合。
最早接触C语言是高中时候, 那时一帮搞奥数的同学,有人带了一本谭浩强的书,于是大家学得热火朝天。师大附中的3年,是人生最自卑的3年。一个宿舍8个人, 湖南省前6名就有4个被宿舍牛人占了。这3年最大的打击就是自己智商怎么怎么低。有人说搞IT的都智商比较高, 那看和谁比了, 和搞数学的比,就基本全是弱智了。记得那时看了一个月,也没明白赋值是怎么回事。宿舍一哥们, 看了一个星期就搞懂了。一打听, 妈的, 人家中考700分考695的。心理压力那个大啊。
然后就是3年后,99年到了上海, 第一门课就是C++语言。 那时是面向对象的顶峰。我也免不了。凭着自己的小聪明, 一个暑假看完同济大学的高等数学, 然后第一学期的高数免修时间就全部用来学C++。这一入火坑就是6年。回顾这6年, 我现在后悔了。 脱离实际, 被语言细节玩死了。 看了一大堆书, 懂一大堆理论,实际项目到底如何面向对象分析还是一头雾水。 历史如果能够重来, 我情愿学习另一门语言, 英语。回过头来看, 我花了大量时间,看了大量书, 但脱离实际, 基本上是在岸上游。再加上C++语法过于繁杂。
客观上也让学习者找不到北。
其实上, C++最大的问题就是死在搞不懂它的设计哲学。坦率的地说,我学习了6年,工作中又用了4年, 我还是没自信说我懂C++。更主要的是, 我没有搞懂多继承到底怎么用。面向对象里,我最搞不懂的就是继承。继承的最大问题就是破坏封装。这2者的平衡实在是太难掌握了。现在各种面向对象实现版本,继承是最大问题。
首先现实中的继承都是部分继承。 比如,继承父母的财产。你只能继承一部分,不可能继承所有。然后, 是继承父母的性格。但,你会和父母的性格完全一致吗, 显然不可能。
这中间的差别就在于, 虽然能继承A,和B, 但你没有办法让系统自动解决A和B之间的融合, 构建一个新的C。即C很难只继承A类的X函数的部分特性,再继承B类的Y函数的部分特性。如果你直接调用A.X 和B.Y,显然由于A和B是高耦合, 这必然会带来一些副作用。如果要修改这些副作用, 你必然又要影响A和B的封装。矛盾就在于, 作为子类, 你
没有权力修改A和B。 问题的关键就是,现实的继承都有融合和进化。 而目前的面向对象语言基本上很难提供有价值的工具来解决融合和进化。
这样,我们很快就会发现, 系统并没有变得更简单, 反而更复杂了。我们本意是想通过工具来简化系统,却事与愿违,让自己更晕了。
而C为什么没有这个包袱呢? 因为C完全是你自己控制整个融合。只有人才能精确的知道A类哪些属性是自己想要的, 哪些是垃圾数据。只有人才能清楚的知道哪些函数满足isA关系,哪些函数必须丢弃,哪些函数还可以改改用用。
这中间的最大差别是, 你将问题丢给C++, 但事实上它并没有你想的那么强大。而C是完全告诉你,对不起,这个搞不定,必须你自己来。
这样,最终结果就是, 系统虽然对外接口看起来很完美, 里面相互冲突相互矛盾的东西一大堆。你原以为能在下一个系统中完美重用, 却发现一旦抽象的映射关系由于项目的变化,而导致大量的isA关系变成isNotA关系。怎么办? 将上千个类完全重写? 事实上,光自上而下检查所有isA关系就已经让你吐血了。更不用说再在高内聚的类上动刀子解耦。工作这么多年,C++让我最开心的就是,这个库你们负责,我只管调接口。 这的确比C稍微快一点,少敲了一些 void*this, 但如果让我去改某个号称C++高手,其实只是胡乱写了2-3年代码的人,
我只能往上追溯XXX年,(略500字)
当然,上面这个问题不是C++的问题,是所有面向对象语言通用的问题。这些号称无敌的工具, 却完全没有智能, 一旦抽象关系发生变化,它们什么也干不了。而一旦人来维护这些关系的时候, 却发现还不如重写, C+V操作来得快。
我喜欢C的最大原因就是它的哲学: 能干的一定帮你干好, 不能干的你自己必须干好。 决定一切的不是计算机,而是人。
关于效率问题, C一直被人诟病, 其实你完全可以C + 自己构建的语言来解决。 我去年就自己设计了一个简单的语言, 能快速地将描述性代码转换为面向对象版C语言。
谁说C不能面向对象? 说C不能面向对象的人, 其实是自己还没懂面向对象。 看起来好像学了C++, 懂了,其实完全只是为了方便C+V, 却完全不管父类里面10个函数有8个不满足isA关系。 没事,只要我这个项目只用10个中的2个就可以。后面项目有没有,还在不在这个公司谁知道呢?