vlambda博客
学习文章列表

浅谈学习C语言与学习C++语言的关系



本文写给C或C++语言初学者。



常有初学者问“学C++语言前是否要先学C?”。我认为这是个伪问题。问题本身的答案并不是提问人真正想要的。

回答问题本身很简单:“当然不需要”。因为C++是一门独立的编程语言,它在语法、构建环境和运行环境上都无需依赖任何其它语言。至于说它是“C语言的超集”,那只是一种模糊的提法而已,更准确的说法应是:C++语言从设计之初就充分考虑了对C语言的兼容,结果它在很大程度上兼容了C语言。如此而已。

但对于那样提问的初学者来说,以上会是他们想要的答案吗?我觉得不是。至少问题没有这么简单。

C++语言支持多种编程范式:面向过程、面向对象和范型程序设计它所兼容C的部分,正是支持面向过程的主要部分。有C语言的基础,虽然有助于更快地掌握C++的面向过程部分,但由于C++语言本身也直接支持面向过程,因此我们完全可以从C++中直接学习面向过程程序设计,而无需先学C。至少理论上如此。


但话又要说回来。注意,这么提问的大多是初学者。一般讲解C++语言的教程,限于篇幅,面向过程部分无法与一本优秀的C语言教程相媲美。于是,真正的问题来了:直接从C++语言开始学习的初学者,他是否愿意像C语言初学者那样花大量的时间和精力,专门钻研面向过程程序设计呢?如果他不愿,那么他对面向过程部分的掌握,就难以跟一个扎扎实实学习过C语言的人相比。即使只讨论“C++中的C”,结论也一样。但是,这里我只是想强调这样一个事实,而并非要下个“必须先学C”的结论。

我个人在初学C++语言时,觉得教程中学到的好多东西,包括面向对象程序设计,在实践中无法运用自如。后来因工作需要,又去学习Java语言,之后对面向对象有了一点开窍的感觉。再使用C++写程序时,发现OO起来也更顺畅了,我的好几位朋友也有过类似的感觉。究其原因,我想跟上面的分析的C语言情况类似。
C++的所支持的特性和编程范式太多,初学者很难快速消化全部。而Java在1.4之前,可以认为是纯面向对象的。这样,使用Java写程序时,我们被迫实践面向对象编程,这就好比使用C写程序,我们被迫实践面向过程一样。而直接使用C++写程序,没有什么“被迫”,我们也就缺少了相应的“专项强化训练”。并非所有的人都需要这种“专项强化训练”,但对于初学者,面对着需要掌握的复杂知识体系,它确能起到“分而治之”的作用,从而促进对知识的消化和吸收。

还有人认为,学会了C++语言,自然就学会了C。而我并不认同这种观点。我们必须承认两点:

第一,C语言是有用的,这不用多说,那么多C语言构筑起来的项目和复杂系统摆在那里。虽然没有对包括面向对象在内的各种更抽象的编程范式提供直接支持,但事实证明它能解决复杂问题;

第二,C++语言的设计者所设计的是一门新式的语言,而不仅仅是一个“更好用的C”。这导致C++在继承C语言的同时也要对它的各种特性做必要的扬弃。于是,就产生了很多这样的情况:某种特性,在C语言中非常重要,但C++语言却拥有一些新的特性来替代它,而且可能做得更好。这样,原来C语言中的一些特性在C++语言中虽然还被兼容,却被大大淡化,或不再提倡,甚至一些C++语言的教程中提都不提了。这方面的例子很多,比如“宏”,C++中有太多可以在各种不同的场合取代宏的东西;再比如可变参数,还有对指针的一些复杂使用等等。这些东西在C语言中却非常重要,重要到成为C语言之所以“有用”的直接原因之一。因为这些原因,一个用惯了C++语言,而从没单独学习过C语言的人,如果有一天突然被要求去负责一个C语言项目,我不认为他一定能轻松搞定。所以,我认为“学会C++,自然也就学会了C”的观点是没有道理的。

有人说过,“C语言是结构化的汇编”,没错,它的功能、效率和可移植性都很好地达到了它的设计初衷,它对现实项目中的各种问题也都有它独特的解决方式,而同样的解决方式在C++语言中却未必是恰当的(反之也成立)。换句话说,从解决实际问题的方式来看,这两种语言谁也包含不了谁。我们学习语言最终不都是为了解决实际问题吗?那结论已经出来了:
C++语言从语法上几乎完全包含了C不代表它“真正”包含了C。
反过来,一个熟练掌握了C语言的程序员,学习C++语言的情况又是怎样的呢?正如前面分析过,C语言面向过程的“专项训练”非常有助于迅速掌握C++语言的面向过程部分;而且,大多数人最终都在实际的软件开发中运用编程语言,这使得任何语言的编程背景对其它新语言的学习都会有帮助,比如说学习BASIC也可以认为对学习C++有帮助。但不同的语言毕竟是不同的语言,C语言和C++语言终归体现了不同的编程思想,如果在学习C++语言的过程中,不能适时的忘记并跳出C,有时可能阻碍对C++编程思想的理解和掌握。

最后,有必要提一下,C语言在其最新的标准中还加入了一些新的特性,它们当中的一些C++语言没有办法直接“兼容”,甚至未来的C++语言也不一定会兼容它们。比如栈上分配的动态数组。

总结一下:

(1)学习C++语言不需要以任何其它语言作为基础,包括C;
(2)不要指望学会了C++语言,就等于同时掌握C++跟C;
(3)也不要指望学过一遍C++语言,面向过程的编程水平就一下子可以跟上专门学习过C语言的程序员;
(4)学好了C,对学习C++有很大的帮助,但要更好的学习C++语言并掌握其编程思想,有时需适时地忘记并跳出C。

再浓缩一下,其实只想说一句话:
C和C++是两门不同的编程语言,只是它们有较大的联系。






2020年6月11日 晚


随手点赞分享,是对我最大的支持