学C++要不要先学C语言?

Posted 人邮异步社区

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了学C++要不要先学C语言?相关的知识,希望对你有一定的参考价值。

我对C或C++ 都不了解,是不是应该先学习C?不,首先学习C++。C++ 的C子集对于C/C++ 的新手是比较容易学的,又比C本身容易使用。原因是C++(通过强类型检查)提供了比C更好的保证。进一步说,C++ 还提供许多小特征,例如运算符new,与C语言对应的东西相比,它们的写法更方便,也更不容易出错。这样,如果你计划学习C和C++(而不只是C++),你不应该经由C那条迂回的路径。为能很好地使用C,你需要知道许多窍门和技术,这些东西在C++ 里的任何地方都不像它们在C里那么重要、那么常用。好的C教科书倾向于(也很合理)强调那些你将来在用C做完整的大项目时所需要的各种技术。好的C++ 教科书则不太一样,强调能引导你去做数据抽象、面向对象的程序设计的技术和特征。理解了C++ 的各种结构,而后学习它们在(更低级的)C里替代物将会很简单(如果需要的话)。

要说我的喜好:要学习C,就用 [Kernighan,1988];要学习C++,就用[2nd]。两本书的优点是都组合了两方面内容:一方面是关于语言特征和技术的指导性的描述,另一方面是一部完整的参考手册。两者描述的都是各自的语言而不是特定的实现,也不企图去描述与特定实现一起发布的特殊程序库。

现在有许多很好的教科书和许多各种各样风格的材料,上面只是我对理解有关概念和风格的喜好。请仔细选择至少两个信息来源,以弥补可能的片面性甚至缺陷,这样做永远是一种明智之举。

我在一开始应该把C++ 作为一种OOPL,还是作为一个更好的C语言?看情况。为什么你想开始用C++?对这个问题的回答应该能确定你走近C++ 的方式,在这里,没有某种放之四海而皆准的道理。按照我的经验,最安全的方式是自下而上地学习C++,也就是说,首先学习C++ 所提供的传统的过程性程序设计特征,也就是那个更好的C子集;而后学着去使用和遵循那些数据抽象特征;再往后学习使用类分层去组织相互有关的类的集合。

按照我的观点,过快地通过早期阶段是很危险的,这样会使忽视某些重要概念的可能性变得非常之大。

例如,一个有经验的C程序员可能会认为C[3]的更好的C子集是‘很熟悉的’,因此跳过了教科书中描述这方面的前100页或多少页。但在这样做时,这个C程序员可能就没看到有关函数的重载能力,有关初始化和赋值之间差异的解释,用运算符new做存储分配,关于引用的解释,或许还有其他一些小特征。在后面阶段它们会不断地跳出来缠住你,而在这时,一些真正的新概念正在复杂的问题中发挥着作用。如果在更好的C中所用的概念都是已知的,读过这100页可能也就只要几个小时的时间,其中的一些细节又是有趣的,很有用的。如果没有读,后面花的时间可能更多。

有些人表达了一种担心,害怕这种‘逐步方式’会引导人们永远去写C语言风格的东西。这当然是一种可能的后果,但是从百分比看,与在教学中采用‘更纯的’语言或者强迫的方式相比,很难说这样做就一定更不值得信任。关键是应该认识到,要把C++ 很好地用作数据抽象和/或面向对象的语言,应该理解几个新概念,而它们与C或者Pascal一类语言并不是针锋相对的。

C++ 并不只是用新语法表述一些老概念——至少对于大部分程序员而言不是这样。这也就隐含着教育的需要,而不仅仅是训练。新概念需要通过实践去学习和掌握。老的反复试验过的工作习惯需要重新评价。不再是按照‘老传统的方式’向前冲,而是必须考虑新方式——通常,与按照老方式相比,以新方式做事情,特别是第一次这样做时,一定更困难,也更费时间。

许多经验说明,对大部分程序员而言,花时间和精力去学习关键性的数据抽象和面向对象技术,是非常有价值。并不是必须经过很长的时间才能产生效益,一般在3到12个月就可以。不花这些精力,而只是使用C++,也会有效益,但最大的效益还是要在为学习新概念而花费精力之后——我的疑问是,如果什么人不想花这个精力,那么为什么还要转到C++ 来呢。

在第一次接触C++,或是在许多时间之后又第一次接触它,用一点时间去读一本好的教科书,或者几篇经过很好选择的文章(在The C++ ReportThe C++ Journal里有许多这样的文章)。你也可能想看看某些主要的库的定义和源代码,分析其中使用的概念和技术。对那些已经用了一段C++ 的人来说,这也是个好主意,在重温这些概念和技术的过程中可以做许多事情。自C++ 第一次出现以来,在C++ 语言以及与之相关的编程和设计技术方面已经发生过许多事情。将《C++ 程序设计语言》的第1版和第2版做一个简单对比,就足以使人相信这个说法。

学习C++ 需要花多少时间?同样要看情况。依赖于你的经验,也依赖于你所说的‘学习C++’的意思。对大部分程序员而言,学习语法和用更好的C的风格写C++,再加上定义和使用几个简单的类,只要一两周时间。这是最容易的部分。最主要的困难在于掌握新的定义和编程技术,这也是最有意思、最有收获的部分。曾经和我讨论过的大部分有经验的程序员说,他们用了半年到一年半时间,才真正觉得对C++ 适应了,掌握了它所支持的数据抽象和面向对象技术。这里假定他们是在工作中学习并维持着生产——通常在此期间也用着C++的某种‘不那么大胆’的风格做程序设计。如果你能拿出全部时间学C++,就可能更快地适应它。但是,在没有将新的思想和设计应用到真实的项目中之前,这个适应也很可能是骗人的。面向对象的编程和面向对象的设计,基本上是实践性的训练而不是理论训练。只是对一些玩具式的小例子使用或者不使用它,这些思想就很可能演化为一种危险的盲从倾向。

请注意,学习C++,最根本的是学习编程和设计技术,而不是语言细节。在做完了一本教科书的学习工作之后,我会建议一本有关设计的书,例如 [Booch,1991] [4],该书里有一些稍长的例子,用的是5种语言(Ada、CLOS、CLU、C++、Smalltalk和Object Pascal),这样就可能在某种程度上避免语言的偏狭性,而偏狭性已经弄糟了许多有关设计的讨论。在这本书里,我最喜欢的部分就是描述设计概念和例子的那几章。

关注设计方式,与非常仔细地关注C++ 的定义细节(例如ARM,其中包含许多有用的信息,但是没有关于如何用C++ 编程的信息)是截然不同的。把注意力集中到细节上,很容易把人搞得头昏脑涨,以至于根本就用不好语言。你大概不会试着从字典和语法去学习一种外国语吧?

在学习C++ 时,最根本的,应该是牢记关键性的设计概念,使自己不在语言的技术细节中迷失了方向。如果能做到这一点,学习和使用C++ 就会是非常有趣的和收效显著的。与C比较,用一点点C++ 就可能带来许多收获。在理解数据抽象和面向对象技术方面付出进一步努力,你将能得到更多的收获。”

这个观点也不是全面的,受到当前工具和库的状况的影响。如果有了保护性更强的环境(例如包括了广泛的自动的运行时检查)以及一个小的定义良好的基础库,你就可以更早地转到大胆使用C++ 的方面去。这些将能更好地支持从关注C++ 的语言特征到关注C++ 所支持的设计和编程技术的大转移。

分散一些兴趣放到语法上,把一些时间用到语言的技术细节上,也是非常重要的。有些老牌程序员喜欢翻弄这些细节。这种兴趣与不大情愿去学习新的程序设计技术,经常是很难分辨清楚的。

类似地,在每个课程和每个项目里总有这样的人,他们根本不相信C++ 的特征是可以负担得起的,因此在后来的工作中坚持使用自己更熟悉和信任的C子集。只有不多的有关个别C++ 特征和用C++ 写出的系统的执行效率方面的数据(例如,[Russo,1988]、[Russo,1990]、[Keffer,1992]),不大可能动摇这些人长期而牢固的,有关比C更方便的机制是不可能负担的观点。看到这种宣传的量,与语言或工具领域中未得到满足的允诺的量的比较,人们应该对这种说法持怀疑态度,并要求拿出更明显的证据。

以上回答摘自C++之父Bjarne Stroustrup(本贾尼·斯特劳斯特卢普 )的《C++语言的设计和演化

你懂得C,所以C++不在话下

你懂得C,所以C++不在话下,是吗?也许如此。大部分C++书籍都有三四百页厚,排版密密麻麻。你如果沉湎于它的细节之中,很容易迷失方向,无法从中寻找到它的真正要旨。另一方面,从实用的角度讲,C++是ANSI C的一个超集,它基本上兼容ANSI C。不过C语言的有些特性在C++中并不支持,本章的最后有一张表,列出了这些特性。但是,要想从C++中获益,或甚至完全理解它,必须理解一些基础概念。这就是人们谈论使用C++编程时“object-oriented paradigm(面向对象编程模型)”和“转换思维”的意思。我去掉了C++中的一些神秘之处,尽量用平实的语言来描述C++,把它与你所熟悉的C语言特性联系起来,帮助你尽快入门。

这有点类似于窗口接口编程模型。有时我们需要从窗口系统的角度,学习改写自己的程序,此时的控制逻辑就要转变成主窗口循环处理。OOP也差不多,但它是从改写数据类型的角度对程序进行改写。

面向对象编程(OOP)并不是一个新鲜想法,Simula67是这个概念的先驱,迄今已超过四分之一个世纪了。面向对象编程很自然地把使用对象作为程序设计的中心主题。软件对象的定义有很多种,其中绝大多数定义都同意面向对象的关键就是把一些数据和对这些数据进行操作的代码组合在一起,并用某种时髦手法将它们做成一个单元。许多编程语言把这种类型的单元称为“class(类)”。关于面向对象编程的廉价定义也有很多,通常只有在你理解了OOP是什么以后才能对这些定义品头论足。其中一种定义如下:

面向对象编程的特点是继承和动态绑定。C++通过类的派生支持继承,通过虚拟函数支持动态绑定。虚拟函数提供了一种封装类体系实现细节的方法。

嗯,看明白了吗?我将带领大家进行一次C++的轻松之旅,只讲述那些需要高度重视的东西。我们将省掉很多不太重要的细节,这样,理解C++语言框架的任务便大大减轻。我们的方法是领会一些OOP的关键概念,并总结C++的相关特性是如何支持它们的。这里提到的概念是按照逻辑顺序依次出现的,后面出现的概念一般都建立在前面出现的概念的基础上。有些编程实例有意与日常生活行为相关联,如挤橙汁。当然挤橙汁一般并不是通过软件方法来实现的。这里,我们将调用函数来进行这个操作,把焦点集中于抽象概念而不是底层实现细节中。首先,让我们总结一些术语,并使用在C语言中已经熟悉的概念来描述它们(见表11-1)。

表11-1 面向对象编程的关键概念

术语定义
抽象(abstraction)它是一个去除对象中不重要的细节的过程,只有那些描述了对象的本质特征的关键点才被保留。抽象是一种设计活动,其他的概念都是提供抽象的OOP特性
类(class)类是一种用户定义类型,就好像是int这样的内置类型一样。内置类型已经有了一套完善的针对它的操作(如算术运算等),类机制也必须允许程序员规定他所定义的类能够进行的操作。类里面的任何东西被称为类的成员
对象(object)某个类的一个特定变量,就像j可能是int类型的一个变量一样。对象也可以被称作类的实例(instance)
封装(encapsulation)把类型、数据和函数组合在一起,组成一个类。在C语言中,头文件就是一个非常脆弱的封装实例。它之所以是一个微不足道的封装例子,是因为它的组合形式是纯词法意义上的,编译器并不知道头文件是一个语义单位
继承(inheritance)这是一个很大的概念——允许类从一个更简单的基类中接收数据结构和函数。派生类获得基类的数据和操作,并可以根据需要对它们进行改写,也可以在派生类中增加新的数据和函数成员。在C语言里不存在继承的概念,没有任何东西可以模拟这个特性

1985年以前,C++的名字是“C with Classes”,但现在人们已经在其中加入了非常非常多的特性。从当时的角度看,“C with Classes”是C语言的一个相当合理的扩展,很容易解释、实现和教学。随即,人们对这门语言投入了极大的热情,至今未曾衰减。有许多特性被加入到C++中(有厨房洗水槽之称)。为了制止这种趋势,曾有人建议C++“在增加特性方面应该保守”,也就是在C++中增加新特性应该服从等比增长规则。你想增加多重继承吗?可以!不过异常和模板就只能割爱了!

现在的C++是一个相当庞大的语言。具体地说,一个C编译器的前端大约有40000行代码左右,而一个C++编译器的前端的代码可能是它的两倍,甚至更多。

小启发

从C转换到C++
学习C++最好的方式就是从它的ANSI C子集开始编程。避免使用早期基于CFront的编译器,它所产生的是C代码而不是机器代码。把C语言作为一种可移植的机器语言事实上会使链接和调试复杂化,因为CFront把所有的函数名字混合在一起,为参数信息编写内部代码。名字混合并不可靠,它会带来可怕的危险,并可能长期存在于C++中。与C++相反,Ada对这个问题的处理非常得体,而且它并不使用不正规的实现方法来定义语言的语义。名字混合是一种在不同的文件之间进行类型检查时采用的权宜之策,但它暗示你所有的C++代码必须用同一个编译器编译,因为名字混合策略在不同的编译器上可能各不相同。对于C++的复用模型而言,这是一个巨大的缺陷,因为它有效地防止了二进制一级的复用。
这里有一个代表性的例子,说明了C语言并非C++的子集的部分,并提示何处可能隐藏着麻烦。
在C++中存在,但在C语言中却不存在的限制有:
  • 在C++中,用户代码不能调用main()函数,但在C语言中却是允许的(不过这种情况极为罕见)。
  • 完整的函数原型声明在C++中是必须的,但在C语言中却没这么严格。
  • 在C++中,由typedef定义的名字不能与已有的结构标签冲突,但在C语言中却是允许的(它们分属不同的名字空间)。
  • 当void*指针赋值给另一个类型的指针时,C++规定必须进行强制类型转换,但在C语言中却无必要。

在C++和C语言中含义不一样的特性:

  • C++至少增加了十几个关键字。这些关键字在C语言中可以作为标识符使用,但如果这样做了,用C++编译器编译这些代码时就会产生错误信息。
  • 在C++中,声明可以出现在语句可以出现的任何地方。在C语言中的代码块中,所有的声明必须出现在所有语句的前面。
  • 在C++中,一个内层作用域的结构名将会隐藏外层空间中相同的对象名。在C语言中则非如此。
  • 在C++中,字符常量的类型是char,但在C语言中,它们的类型是int。也就是说,在C++中,sizeof(‘a’)的结果是1,而在C语言中,它的值要大一些。
  • 由于C++增加了新的//注释符,有时会在两种语言中产生微妙而怪异的差别(第2章对这个问题已有所描述)。

C和C++之间的不同之处还有很多,但现在你已经知道了足够多的可能引起危险的情况。所以你要保持警惕,避免危险的出现。当对编译器和所有用于ANSI C这个C++子集的工具了如指掌时,便可以展开翅膀,定义自己的类。选择一本优秀的C++书籍(浏览数册,选择一本在风格上你最喜欢的),注意它必须把握住这门语言的脉搏(C++语言仍在发展之中),它必须涵盖异常和模板,这两个特性是迄今为止最晚加入到C++中的。

和C语言一样,C++语言的标准化也是由ISO和ANSI X3J16一起进行的。最乐观的估计也需要六年,也就是1996年,才能完成C++语言的标准化。注意你的书中应该提及ANSI C++的进展。

以上回答摘自《C专家编程》

C/C++入门书籍推荐

C++ Primer Plus 第6版

C++程序设计教程,C++大百科全书,零基础自学C++入门图书,赠送价值99元的e读版电子书及在线实验环境,赠送大尺寸全书思维导图。

《C++ Primer Plus(第6版)中文版》分18章,分别介绍了C++程序的运行方式、基本数据类型、复合数据类型、循环和关系表达式、分支语句和逻辑运算符、函数重载和函数模板、内存模型和名称空间、类的设计和使用、多态、虚函数、动态内存分配、继承、代码重用、友元、异常处理技术、string类和标准模板库、输入/输出、C++11新增功能等内容。

《C++ Primer Plus(第6版)中文版》针对C++初学者,从C语言基础知识开始介绍,然后在此基础上详细阐述C++新增的特性,因此不要求读者有C语言方面的背景知识。《C++ Primer Plus(第6版)中文版》可作为高等院校教授C++课程的教材,也可供初学者自学C++时使用。

2、C Primer Plus(第6版)中文版

C语言入门教程,C语言程序设计籍,程序员的启蒙教材,针对C11标准库更新。

《C Primer Plus(第6版)中文版》共17章。第1章、第2章介绍了C语言编程的预备知识。第3章~第15章详细讲解了C语言的相关知识,包括数据类型、格式化输入/输出、运算符、表达式、语句、循环、字符输入和输出、函数、数组和指针、字符和字符串函数、内存管理、文件输入和输出、结构、位操作等。第16章、第17章介绍C预处理器、C库和高级数据表示。本书以丰富多样的程序为例,讲解C语言的知识要点和注意事项。每章末尾设计了大量复习题和编程练习,帮助读者巩固所学知识和提高实际编程能力。附录给出了各章复习题的参考答案和丰富的参考资料。

《C Primer Plus(第6版)中文版》可作为C语言的教材,适用于需要系统学习C语言的初学者,也适用于想要巩固C语言知识或希望进一步提高编程技术的程序员。

以上是关于学C++要不要先学C语言?的主要内容,如果未能解决你的问题,请参考以下文章

Spring Boot 要怎么学?要学哪些东西?要不要先学 SSM?松哥说说看法

干货 | 学习大数据为什么要先学Java?

c++和python先学哪个?

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

学习C++需要先学C吗,为啥?

C++和python先学哪个