21天学通C++(第8版)

978-7-115-46588-7
作者: 【美】Siddhartha Rao(悉达多 饶)
译者: 袁国忠
编辑: 傅道坤
分类: C++

图书目录:

详情

本书是当今市场上最受欢迎的轻量级C++学习教程,在讲解C++基本知识(如变量、数组、循环、线程)和高级主题(如面向对象编程、宏和模板的类和对象)的同时,还涵盖了最新的C++标准模板库(STL)等在内的知识。

图书摘要

版权信息

书名:21天学通C++(第8版)

ISBN:978-7-115-46588-7

本书由人民邮电出版社发行数字版。版权所有,侵权必究。

您购买的人民邮电出版社电子书仅供您个人使用,未经授权,不得以任何方式复制和传播本书内容。

我们愿意相信读者具有这样的良知和觉悟,与我们共同保护知识产权。

如果购买者有侵权行为,我们可能对该用户实施包括但不限于关闭该帐号等维权措施,并可能追究法律责任。

• 著    [美] Siddhartha Rao

  译    袁国忠

  责任编辑 傅道坤

• 人民邮电出版社出版发行  北京市丰台区成寿寺路11号

  邮编 100164  电子邮件 315@ptpress.com.cn

  网址 http://www.ptpress.com.cn

• 读者服务热线:(010)81055410

  反盗版热线:(010)81055315


Siddhartha Rao: Sams Teach Yourself C++ in One Hour a Day(8th Edition)

ISBN: 0789757745

Copyright © 2017 by Pearson Education, Inc.

Authorized translation from the English languages edition published by Pearson Education, Inc.

All rights reserved.

本书中文简体字版由美国Pearson公司授权人民邮电出版社出版。未经出版者书面许可,对本书任何部分不得以任何方式复制或抄袭。

版权所有,侵权必究。


本书通过大量短小精悍的程序详细而全面地阐述了C++基本概念和技术,以及C++11、C++14和C++17新增的功能,包括管理输入/输出、循环和数组、面向对象编程、模板、使用标准模板库、列表初始化、lambda表达式、自动类型推断等。这些内容被组织成结构合理、联系紧密的章节,每章都可在1小时内阅读完毕;每章都提供了示例程序清单,并辅以示例输出和代码分析,以阐述该章介绍的主题。为加深读者对所学内容的理解,每章末尾都提供了常见问题及其答案以及练习和测验。读者可对照附录E提供的测验和练习答案,了解自己对所学内容的掌握程度。

本书是针对C++初学者编写的,不要求读者有C语言方面的背景知识,可作为高等院校教授C++课程的教材,也可供初学者自学C++时使用。


Siddhartha Rao是全球领先的企业软件提供商SAP SE负责安全响应的副总裁。C++的发展让他深信,您能编写速度更快、更简洁、更强大的C++应用程序。Siddhartha酷爱旅游,还是山地自行车运动的狂热爱好者;他期待着您对本书的反馈。


谨以本书献给我的父亲,您永远是我的灵感来源。


感谢家人对我无尽的支持,感谢我的妻子Clara,感谢为本书贡献颇多的编辑人员。


对C++来说,2011年和2014年都是很特别的年份。C++11做了重大的改进,新增了一些可提高编程效率的关键字和结构,而C++14做了增量式改进,完善了C++11引入的新特性。

本书旨在帮助您循序渐进地学习C++,其中的章节经过深思熟虑,从实用的角度介绍这种面向对象编程语言的基本知识。读者只需每天花1小时,就能掌握C++。

学习C++的最佳方式是动手实践。本书包含了丰富的代码示例,有助于提高编程技能,请读者务必亲自动手尝试这些代码。这些代码片段都使用了最新版本的编译器进行了测试,具体地说是Microsoft Visual C++和GNU C++编译器,它们都支持大量的C++14功能。

本书从最基本的C++知识开始介绍,读者只需具备学习C++的愿望及了解工作原理的好奇心即可;虽然具备一些C++知识会有所帮助,但这并非必须。本书也可供熟悉C++但想了解其新增功能的读者参考。如果您是专业程序员,第三部分(学习标准模板库)将有助于您创建更优质、更实用的C++应用程序。

读者可根据自己对C++的熟练程度,阅读感兴趣的部分。C++11和C++14引入的新概念散落在本书各个相关的章节中。本书包含如下5部分。

本书使用了下述提供更多信息的元素。

 

提供与读者阅读的内容相关的信息。

 

 

提醒读者注意在特定情况下可能出现的问题或副作用。

 

 

提供C++编程最佳实践。

 

应该

不应该

提供当前章介绍的基本原理的摘要。

提供一些有用的信息。

本书的示例代码可从www.epubit.com/book/details/4780下载。


欢迎使用本书!通过阅读本章,您将迈出成为高级C++程序员的第一步。

在本章中,您将学习:

编程语言旨让人更容易使用计算资源,C++并非一种新语言,但被广泛采用,仍在不断改进。本书编写期间,国际标准组织(ISO)批准的最新C++标准为2014年12月发布的C++14。

C++最初由Bjarne Stroustroup于1979年在贝尔实验室开发,旨在作为C语言的继任者。但不同于C语言,C++是一种面向对象的语言,实现了继承、抽象、多态和封装等概念。C++支持类,而类包含成员数据以及操作成员数据的成员方法。其结果是,程序员需要考虑数据以及要用它们来做什么。一直以来,很多C++编译器都支持C语言。

 

要学习C++,并不要求您具备C语言编程方面的知识和经验。如果您的终极目标是学习C++等面向对象编程语言,并不需要先学习C语言等过程性语言。

C++是一种中级编程语言,这意味着使用它既可以高级编程方式编写应用程序,又可以低级编程方式编写与硬件紧密协作的库。在很多程序员看来,C++既是一种高级语言,让他们能够开发复杂的应用程序,又提供了极大的灵活性,让开发人员能够控制资源的使用和可用性,从而最大限度地提高性能。

虽然有更新的语言面世,如Java以及其他基于.NET的语言,但C++始终深受欢迎并在不断发展。较新的语言因提供了某些功能(如通过垃圾收集管理内存)让一些程序员钟爱有加,但在需要控制应用程序的资源使用和性能时,他们还是会选择C++。当前,在分层架构中,常常使用C++编写Web服务器,并使用HTML、Java或.NET编写其他组件。

经过多年的发展,C++被众多不同的平台接受和采纳,这些平台使用不同的编译器。鉴于不同的编译器之间存在差异,这导致了众多互操作性和移植方面的问题,因此需要对C++进行标准化,让编译器厂商能够遵循标准的C++语言规范。

1998年,第一个C++标准获得了ISO标准委员会的批准,这就是ISO/IEC 14882:1998。从此以后,C++标准发生了翻天覆地的变化,极大地提高了C++语言的可用性,并扩展了对标准库的支持。编写本书期间,获得批准的最新标准为ISO/IEC 14882:2014,俗称C++14。

 

并非所有流行的编译器都会迅速而全面地支持最新标准,因此虽然从学术角度看,最好了解最新标准新增的功能,但就编写良好的C++应用程序而言,这些新增功能并非是必不可少的。

使用C++编写的应用程序、操作系统、Web服务、数据库和企业软件多如牛毛,因此无论您从事什么工作,使用计算机来做什么,都可能正在使用C++编写的软件。除软件工程师外,C++还常被物理学家和数学家用来从事研究工作。

当您在Windows系统上启动Notepad或在Linux系统上启动Terminal时,实际上是命令处理器运行该程序的可执行文件。可执行文件是可运行的成品,应按程序员期望的那样做。

要创建可在操作系统中运行的可执行文件,第一步是编写一个C++程序。创建C++应用程序的基本步骤如下。

1.使用文本编辑器编写C++代码。

2.使用C++编译器对代码进行编译,将代码转换为包含在目标文件中的机器语言版本。

3.使用链接器链接编译器的输出,生成一个可执行文件(如Windows中的.exe文件)。

在编译过程中,C++代码(通常包含在.cpp文本文件中)被转换为处理器能够执行的字节码。编译器每次转换一个代码文件,生成一个扩展名为.o或.obj的目标文件,并忽略这个cpp文件可能对其他文件中代码的依赖。解析这些依存关系的工作由链接程序负责,如果链接成功,则创建一个可执行文件,供程序员执行和分发。整个过程也被称为构建可执行文件。

大多数应用程序很少能够一次通过编译并按预期运行。无论使用什么语言(包括C++)编写,庞大或复杂的应用程序都需要运行很多次,以便通过测试来找出代码中的错误,即bug。修复bug后,重新生成程序,再重复测试过程。因此,除编写、编译和链接等3个步骤外,软件开发过程通常还包括调试步骤。在这个步骤中,程序员对代码中的错误进行分析和修复。优秀的开发环境提供了帮助调试的工具和功能。

很多程序员都喜欢使用集成开发环境(Integrated Development Environment,IDE)。集成开发环境让您能够在一个统一的用户界面中完成输入、编译和链接步骤,它还提供了调试功能,让您能够更轻松地发现错误并解决问题。

 

要编写、编译并执行C++应用程序,最快捷的方式是通过浏览器来使用在线IDE,如http://www.tutorialspoint.com/compile_cpp_online.php。

另外,也可安装众多免费的C++ IDE和编译器。在Windows和Linux系统中,最流行的分别是Microsoft Visual Studio学习版和GNU C++编译器g++。如果您使用的是Linux系统,要使用g++编译器来开发C++应用程序,可安装免费的Eclipse IDE。

应该

不应该

保存文件时,务必使用扩展名.cpp。 使用简单文本编辑器或集成开发环境来编写代码。

保存C++代码文件时,不要使用扩展名.c,因为有些编译器都将这种文件视为C语言代码,而不是C++代码。 不要使用字处理器等富文本编辑器,因为它们经常会给您编写的代码添加标记。

了解工具和步骤后,该编写第一个C++应用程序了,它在屏幕上打印Hello World!。

如果您使用的是Linux操作系统,使用简单的文本编辑器(我使用gedit)创建一个包含程序清单1.1所示内容的CPP文件。

如果您使用的是Windows操作系统和Microsoft Visual Studio,可采取如下步骤。

1.选择菜单“文件”>“新建项目”打开新建项目向导。

2.选择Visual C++下的“Win32控制台应用程序”,并将项目命令为Hello,再单击“确定”按钮。

3.在“应用程序设置”下,取消选择复选框“预编译头”,再单击“完成”按钮。

4.用程序清单1.1所示的代码替换Hello.cpp中自动生成的内容。

程序清单1.1 Hello Wrold程序(Hello.cpp)

1:  #include <iostream>
2:
3:  int main()
4:  {
5:    std::cout << "Hello World!" << std::endl;
6:    return 0;
7:  }

这个应用程序很简单,只是使用std::cout在屏幕上显示一行消息。std::endl命令cout换行。该应用程序退出时向操作系统返回0。

 

默读程序时,知道特殊字符和关键字的发音可能会有所帮助。

例如,对于#include,可读作hash-include、sharp-include或pound-include,这取决于您以前的背景。

同样,对于std::cout,可读作standard-c-out,而endl可读作end-line。

 

 

别忘了,魔鬼隐藏在细节中,这意味着您必须准确地输入程序清单中的代码。编译器对代码的要求非常严格;语句必须以;结尾,如果您错误地输入了:,编译将以失败告终,并出现大量的错误消息。

如果您使用的是Linux系统,请打开终端,切换到文件Hello.cpp所在的目录,再使用如下命令行调用g++编译器和链接程序:

g++ -o hello Hello.cpp

该命令行让g++编译C++文件Hello.cpp,并创建一个名为hello的可执行文件。

如果您使用的是Microsoft Viusual Studio,可在该IDE中按Ctrl + F5直接运行程序。这将编译、链接并执行应用程序。也可依次执行如下步骤。

1.右击项目并选择“生成”,这将生成可执行文件Hello.exe。

2.在命令提示符中,切换到可执行文件所属的文件夹(通常是项目文件夹中的Debug文件夹)。

3.输入可执行文件的名称以运行它。

在Microsoft Visual Studio中编写的程序与图1.1极其相似。

图1.1 在Microsoft Visual Studio学习版中创建的简单C++程序“Hello World”

在Linux和Windows系统中,分别执行./hello或Hello.exe,这将返回如下输出:

Hello World!

祝贺您踏上了学习有史以来最流行、最强大的编程语言之一的道路!

C++ IOS标准的意义

 

正如您看到的,通过遵守标准,可在多种平台(或操作系统)中编译和执行程序清单1.1所示的代码——前提条件是遵守了标准的C++编译器。因此,如果要编写让Windows用户和Linux用户都能运行的软件,通过在编程中遵守标准(不使用编译器或平台特有的语义)是一种获取更多用户的简单方式,这让您无需针对要支持的每种环境进行编程。当然,编写不需要在操作系统级进行大量交互的应用程序时,这种方法的效果最佳。

编译器的要求非常苛刻,但优秀的编译器会相当明确地指出错误在什么地方。如果您在编译程序清单1.1所示的应用程序时遇到问题,错误消息将与下面的内容极其相似(这是故意省略第5行末尾的分号导致的错误):

hello.cpp(6): error C2143: syntax error : missing ';' before 'return'

这条错误消息来自Visual C++编译器,对错误进行了详细描述。它指出了包含错误的文件的名称,在哪一行遗漏了分号(这里是第6行),还使用错误编号(这里是C2143)对错误本身进行了描述。在这个例子中,虽然遗漏分号的是第5行,但错误消息却指出错误发生在第6行,这是因为对编译器来说,只有等它分析完return语句,而且这条return语句指出前一条语句应该被终止后,错误才更明显。如果您在第6行开头添加分号,程序将通过编译!

 

不同于VBScript等语言,在C++中分行并不能自动结束语句。

在C++中,一条语句可跨越多行;还可在一行中包含多条语句,只要每条语句都以;结尾。

如果您是经验丰富的C++程序员,可能发现程序清单1.1所示的基本程序没有任何变化。虽然C++向后与以前的C++版本兼容,但做了大量工作让这种语言使用起来更容易。

最近一次对C++所做的重大更新是2011年发布的ISO标准,这个标准俗称C++11。2014年发布了C++14,但它只对C++11做了细微的改进和修订。

C++11引入的新功能auto让您能够定义这样的变量,即编译器将自动推断其类型,这简化了变量声明,同时又不影响类型安全。C++14将这种功能扩展到了返回类型。Lambda函数是没有名称的函数,让您能够编写紧凑的函数对象,而无需提供冗长的类定义,从而极大地减少了代码。

C++让程序员能够编写可移植的多线程C++应用程序,同时确保它们遵守标准。这些应用程序支持并行执行范式,在用户升级到多核CPU以改善硬件配置时,其性能将相应地提升。本书将讨论C++所做的众多改进,这里列举的只是其中几项。

在下一次重大修订(C++17)中,有望引入一些新功能,这将在本书的第29章介绍。

在本章中,您学习了如何编写、编译、链接和执行第一个C++程序。本章还简要地介绍了C++的发展历程,并演示了如何在不同的操作系统中使用不同的编译器对同一个程序进行编译,从而证明了标准的重要意义。

问:可以忽略编译器发出的警告消息吗?

答:在有些情况下,编译器会发出警告消息。警告与错误的不同之处在于,相关代码行的语法是正确的,能够通过编译,但可能有更佳的编写方式。优秀编译器在发出警告的同时提供修复建议。

修复建议可能是一种更安全的编程方式,也能让应用程序处理非拉丁语字符和符号。您应该留意警告,并相应地改进应用程序。除非您确定警告是误报,否则不要对其视而不见。

问:解释型语言与编译型语言有何不同?

答:诸如Windows Script等语言是解释型的,不需要编译。解释型语言使用解释器,解释器直接读取脚本文件(代码)并执行指定的操作。因此,要在计算机上执行脚本,必须安装解释器。在运行阶段,解释器在微处理器和代码之间充当翻译,因此性能通常会受到影响。

问:什么是运行时错误?它与编译时错误有何不同?

答:执行应用程序时发生的错误称为运行时错误。在较旧的Windows版本中,您可能遇到过臭名昭著的“非法访问(Access Violation)”错误,它就是运行时错误。最终用户不会遇到编译时错误,这种错误表明程序存在语法问题,会禁止程序员生成可执行文件。

作业包括测验和练习,前者帮助加深读者对所学知识的理解,后者提供了使用新学知识的机会。请尽量先完成测验和练习题,然后再对照附录E的答案,继续学习下一章前,请务必弄懂这些答案。

1.解释器和编译器有何不同?

2.链接器的作用是什么?

3.正常的开发周期包括哪些步骤?

1.阅读下面的程序,在不运行它的情况下猜测其功能。

 1: #include <iostream>
 2: int main()
 3: {
 4:   int x = 8;
 5:   int y = 6;
 6:   std::cout << std::endl;
 7:   std::cout << x - y << " " << x * y << " " << x + y;
 8:   std::cout << std::endl;
 9:   return 0;
10: }

2.输入练习1中的程序,然后编译并链接它。它做什么?与您的猜测相符吗?

3.下面的程序存在什么样的错误?

1: include <iostream>
2: int main()
3: {
4:     std::cout << "Hello Buggy World \n";
5:     return 0;
6: }

4.修复练习3中程序的错误,重新编译、链接并运行它。它做什么?


C++程序被组织成类,而类由成员函数和成员变量组成。本书的大部分内容将对这些组成部分进行深入解释,但要了解程序是如何组合在一起的,必须分析一个完整的工作程序。

在本章中,您将学习:

在第1章中,您编写的第一个C++程序只是将句子Hello World打印到屏幕上,虽然如此,却包含C++程序最重要的基本构件。本节将以程序清单2.1为例,对所有程序都包含的重要部分进行分析。

程序清单2.1 HelloWorldAnalysis.cpp:分析一个简单的C++程序

 1: // Preprocessor directive that includes header iostream
 2: #include <iostream>
 3:
 4: // Start of your program: function block main()
 5: int main()
 6: {
 7:    /* Write to the screen */
 8:    std::cout << "Hello World" << std::endl;
 9:
10:    // Return a value to the OS
11:    return 0;
12: }

可将这个C++程序划分为两个部分:以#打头的预处理器编译指令以及以int main( )打头的程序主体。

 

第1、4、7和10行以//或/*打头,它们都是注释,将被编译器忽略。这些注释是供人们阅读的。

注释将在下一节更详细地讨论。

 

在专业人员编写的C++应用程序中,包含开发环境提供的标准头文件,还有程序员自己创建的头文件。编写复杂的应用程序时,通常将其代码放在多个文件中,这使得需要在某些文件中包含其他文件。因此,如果需要在FileA中使用FileB中定义的元素,就需要在前者中包含后者。为此,通常在FileA中使用如下include语句:

这里使用引号而不是尖括号来包含自己创建的头文件。尖括号(<>)通常用于包含标准头文件。

顾名思义,预处理器是一个在编译前运行的工具。预处理器编译指令是向预处理器发出的命令,总是以磅字符#打头。在程序清单2.1中,第2行的#include <filename>让预处理器获取指定文件(这里是iostream)的内容,并将它们放在在编译指令所处的位置。iostream是一个标准头文件,让您能够在第8行使用std::cout将Hello World显示到屏幕上。换句话说,编译器之所以能够编译包含std::cout的第8行,是因为第2行指示预处理器包含了std::cout的定义。

#include "...relative path to FileB\FileB"

 

在很多C++应用程序中,都使用了类似于下面的main( )函数变种:

这符合标准且可以接受,因为其返回类型为int。括号内的内容是提供给程序的参数。该程序可能允许用户执行时提供命令行参数,如:

其中/DoSomethingSpecific是操作系统传递给程序的参数,以便在main (int argc, char* argv[])中进行处理。

预处理器编译指令的后面是程序的主体——main( )函数,执行C++程序时总是从这里开始。声明main( )时,总是在它前面加上int,这是一种标准化约定,表示main( )函数的返回类型为整数。

int main (int argc, char* argv[])

下面来看第8行,它实际执行该程序的功能:

std::cout << "Hello World" << std::endl;
program.exe /DoSomethingSpecific

cout(控制台输出,读作see-out)是将Hello World显示到控制台(即屏幕)的语句。cout是在名称空间std中定义的一个流(因此这里使用了std::cout),这里使用流插入运算符<<将文本Hello World放到这个流中。std::endl用于换行,将其插入流中相当于插入回车。每次需要将新实体插入流中时,都使用了流插入运算符<<。

C++流的优点是,将类似的语义用于另一种类型的流时,将执行不同的操作。例如,要插入到文件而不是控制台,可将插入运算符<<用于std::fstream(而不是std::cout)。因此,流的用法非常直观,使用过一种流(如将文本写入控制台的cout)后,其他流(如帮助将文件存储到磁盘的fstream)使用起来就非常容易。

流将在第27章更详细地讨论。

 

实际文本(包括引号)“Hello World”被称为字符串字面量。

在C++中,除非明确声明了不返回值,否则函数必须返回一个值。main( )也是函数,且总是返回一个整数。这个整数值被返回给操作系统,根据应用程序的性质,这可能很有用,因为大多数操作系统都提供了查询功能,让您能够获悉正常终止的应用程序的返回值。在很多情况下,一个应用程序被另一个应用程序启动,而父应用程序(启动者)想知道子应用程序(被启动者)是否成功地完成了其任务。程序员可使用main( )的返回值向父应用程序传递成功或错误状态。

 

根据约定,程序员在程序运行成功时返回0,并在出现错误时返回−1。然而,返回值为整数,程序员可利用整个整数范围,指出众多不同的成功或失败状态。

 

 

C++区分大小写,如果将int写成了Int或将std::cout写成了Std::cout,程序将不能通过编译。

在这个程序中,使用的是std::cout而不是cout,原因在于cout位于标准(std)名称空间中。

那么什么是名称空间呢?

假设调用cout时没有使用名称空间限定符,且编译器知道cout存在于两个地方,编译器应调用哪个呢?当然,这会导致冲突,进而无法通过编译。这就是名称空间的用武之地。名称空间是给代码指定的名称,有助于降低命名冲突的风险。通过使用std::cout,您命令编译器调用名称空间std中独一无二的cout。

 

您使用std(读作standard)名称空间来调用获得ISO标准委员会批准的函数、流和工具。

很多程序员发现,使用cout和std名称空间中的其他功能时,在代码中添加std限定符很繁琐。为避免添加该限定符,可使用声明using namespace,如程序清单2.2所示。

程序清单2.2 using namespace声明

 1: // Preprocessor directive
 2: #include <iostream>
 3:
 4: // Start of your program
 5: int main()
 6: {
 7:    // Tell the compiler what namespace to search in
 8:    using namespace std;
 9:
10:    /* Write to the screen using std::cout */
11:    cout << "Hello World" << endl;
12:
13:    // Return a value to the OS
14:    return 0;
15: }
分析:

请注意第8行。通过告诉编译器您要使用名称空间std,在第11行使用cout和endl时,就无需显式地指定名称空间了。

程序清单2.3是程序清单2.2的更严谨版本,它没有包含整个名称空间,而只包含要使用的元素。

程序清单2.3 关键字using的另一种用法

 1: // Preprocessor directive
 2: #include <iostream>
 3:
 4: // Start of your program
 5: int main()
 6: {
 7:    using std::cout;
 8:    using std::endl;
 9:
10:    /* Write to the screen using std::cout */
11:    cout << "Hello World" << endl;
12:
13:    // Return a value to the OS
14:    return 0;
15: }
分析:

在程序清单2.3中,使用第7~8行替换了程序清单2.2的第8行。两者的差别在于,前者让您能够在不显式指定名称空间限定符std::的情况下使用名称空间std中的所有元素(cout、cin等),而后者让您能够在不显式指定名称空间限定符std::的情况下使用std::cout和std::endl。

在程序清单2.3中,第1、4、10和13行包含口语(这里为英语)文本,但不会影响程序编译,也不会影响程序的输出。这些行被称为注释。注释会被编译器忽略,程序员使用它们来对代码进行解释,因此使用人类能够明白的语言编写。

C++支持两种风格的注释。

// This is a comment – won’t be compiled
/* This is a comment
and it spans two lines */

 

程序员为何要对自己编写的代码进行解释呢?这看起来好像有点奇怪,但程序越大、合作开发同一个模块的程序员越多,编写易于理解的代码就越重要。通过使用注释,程序员可指出代码的功能以及为何要这样做。

应该

不应该

务必添加注释,对程序中复杂算法和复杂部分的工作原理进行解释。 务必以其他程序员能够理解的方式编写注释。

不要使用注释来解释显而易见的代码。 别忘了,不要因为可以添加注释,就编写晦涩难懂的代码。 别忘了,修改代码时,可能需要相应地更新注释。

 

在函数无需做任何决策,也无需返回成功/失败状态时,可将其返回类型声明为void:

这个函数不能返回值。

函数让您能够将应用程序划分成多个功能单元,并按您选择的顺序调用。函数被调用时,通常将一个值返回给调用它的函数。最著名的函数无疑是int main( ),它被编译器视为C++应用程序的起点,必须返回一个int(即整数)。

程序员通常需要编写自己的函数。程序清单2.4是一个简单的应用程序,它使用一个函数在屏幕上显示内容,而该函数使用各种参数调用了std::cout。

void DemoConsoleOutput()

程序清单2.4 声明、定义和调用函数,该函数演示了std::cout的功能

 1: #include <iostream>
 2: using namespace std;
 3:
 4: // Declare a function
 5: int DemoConsoleOutput();
 6:
 7: int main()
 8: {
 9:    // Call i.e. invoke the function
10:    DemoConsoleOutput();
11:
12:    return 0;
13: }
14:
15: // Define i.e. implement the previously declared function
16: int DemoConsoleOutput()
17: {
18:    cout << <strong>"</strong>This is a simple string literal" << endl;
19:    cout << "Writing number five: " << 5 << endl;
20:    cout << "Performing division 10 / 5 = " << 10 / 5 << endl;
21:    cout << "Pi when approximated is 22 / 7 = " << 22 / 7 << endl;
22:    cout << "Pi is 22 / 7 = " << 22.0 / 7 << endl;
23:
24:    return 0;
25: }
输出:
This is a simple string literal
Writing number five: 5
Performing division 10 / 5 = 2
Pi when approximated is 22 / 7 = 3
Pi is 22 / 7 = 3.14286
分析:

这里需要注意的是第5、10和16~25行。第5行为函数声明,它告诉编译器您要创建一个函数,该函数名为DemoConsoleOutput( ),返回类型为int。正是因为该声明,编译器才会编译第10行(它在main()中调用DemoConsoleOutput( )),并假定后面会有函数定义(即函数的实现),这里是第16~25行。

这个函数演示了cout的各种功能。它不仅能够像前面显示Hello World那样显示文本,还能显示简单算术运算的结果。第21和22行都试图显示pi的值(22/7),但后者更精确,因为22.0/7让编译器将结果视为实数(在C++中为float),而不是整数。

注意到该函数必须返回一个整数(这里返回的是0),这是在第5行声明的。同样,main( )也返回0。鉴于main( )将其所有任务都交给了函数DemoConsoleOutput( )去完成,更明智的做法是,在main( )中返回该函数的返回值,如程序清单2.5所示。

程序清单2.5 使用函数的返回值

 1: #include <iostream>
 2: using namespace std;
 3:
 4: // Function declaration and definition
 5: int DemoConsoleOutput()
 6: {
 7:    cout << "This is a simple string literal" << endl;
 8:    cout << "Writing number five: " << 5 << endl;
 9:    cout << "Performing division 10 / 5 = " << 10 / 5 << endl;
10:    cout << "Pi when approximated is 22 / 7 = " << 22 / 7 << endl;
11:    cout << "Pi actually is 22 / 7 = " << 22.0 / 7 << endl;
12:
13:    return 0;
14: }
15:
16: int main()
17: {
18:    // Function call with return used to exit
19:    return DemoConsoleOutput();
20: }
分析:

该应用程序的输出与前一个程序清单相同,但编写方式存在细微的差别。首先,由于在main( )前面(第5行)定义了该函数,因此无需声明该函数。较新的C++编译器将其视为函数声明和定义。另外,main( )也更简短。第19行调用函数DemoConsoleOutput( ),并将该函数的返回值作为应用程序的返回值。

函数可以接受参数,可以递归,可以包含多条返回语句,可以重载。函数还可声明为内联的,在这种情况下,编译器将展开函数调用。这些概念都将在第7章更详细地介绍。

计算机让用户能够以各种方式与其运行的应用程序交互,还让应用程序能够以众多方式与用户交互。用户通过键盘和鼠标与应用程序交互。您可以在屏幕上以文本和复杂图形的方式显示信息,使用打印机将信息打印到纸上,还可将信息存储到文件系统中,供以后使用。本节讨论最简单的C++输入输出方式:使用控制台读写信息。

要将简单的文本数据写入到控制台,可使用std::cout(读作standard see-out);要从控制台读取文本和数字,可使用std::cin(读作standard see-in)。事实上,在程序清单2.1中,在屏幕上显示Hello World时,您就使用过cout:

8:    std::cout << "Hello World" << std::endl;

在这条语句中,cout的后面依次为插入运算符<<(帮助将数据插入输出流)、要插入的字符串字面量Hello World、使用std::endl(读作standard end-line)表示的换行符。

cin的用法也很简单,但它用于输入,因此需要指定要将输入数据存储到其中的变量:

std::cin >> Variable;

因此,cin后面依次为提取运算符>>(从输入流中提取数据)以及要将数据存储到其中的变量。如果需要将用户输入存储到两个变量中——每个变量包含用空格分隔的数据,可使用一条语句完成这项任务:

std::cin >> Variable1 >> Variable2;

请注意,cin可用于从用户那里获取文本输入和数字输入,如程序清单2.6所示。

程序清单2.6 使用cin和cout显示用户的数字输入和文本输入

 1: #include <iostream>
 2: #include <string>
 3: using namespace std;
 4:
 5: int main()
 6: {
 7:    // Declare a variable to store an integer
 8:    int inputNumber;
 9:
10:    cout << "Enter an integer: ";
11:
12:    // store integer given user input
13:    cin >> inputNumber;
14:
15:    // The same with text i.e. string data
16:    cout << "Enter your name: ";
17:    string inputName;
18:    cin >> inputName;
19:
20:    cout << inputName << " entered " << inputNumber << endl;
21:
22:    return 0;
23: }
输出:
Enter an integer: 2017
Enter your name: Siddhartha
Siddhartha entered 2017
分析:

第8行声明了一个名为inputNumber的变量,用于存储类型为int的数据。第10行使用cout让用户输入一个数字,而第13行使用cin将输入的数字存储在该int变量中。接下来重复相同的操作,存储用户的名字,当然这不能存储在int变量中,而是存储在string变量中,如第17~18行所示。第2行包含了<string>,原因是后面在main( )中使用了类型string。最后,第20行使用一条cout语句显示输入的名字和数字以及连接文本,输出为Siddhartha entered 2017。

这是一个简单的示例,演示了C++中输入输出的基本原理。如果您不清楚变量的概念,不用担心,第3章将详细阐述。

 

执行程序清单2.6时,如果输入了我的完整姓名Siddhartha Rao,cin依然只会存储第一部分,即Siddhartha。要存储输入的整行内容,应使用函数getline(),这将在第4章讨论。

本章介绍了简单C++程序的基本组成部分。您明白了main( )是什么,了解了名称空间,学习了控制台输入输出的基本知识。现在,您能够在自己编写的任何程序中使用这些知识了。

问:#include的作用是什么?

答:这是一个预处理器编译指令。预处理器在您调用编译器时运行。该指令使得预处理器将include后面的<>中的文件读入程序,其效果如同将这个文件输入到源代码中的这个位置。

问://注释和/*注释之间有何不同?

答://注释到行尾结束;/*注释到*/结束。//注释也被称为单行注释,/*注释通常被称为多行注释。请记住,即使是函数的结尾也不能作为/*注释的结尾,必须加上注释结尾标记*/,否则将出现编译错误。

问:什么情况下需要命令行参数?

答:需要提供让用户能够修改程序行为的选项时。例如,Linux命令ls和Windows命令dir都显示当前目录(文件夹)的内容,要查看另一个目录中的文件,需要使用命令行参数指定相应的路径,如ls /或dir \。

作业包括测验和练习,前者帮助加深读者对所学知识的理解,后者提供了使用新学知识的机会。请尽量先完成测验和练习题,然后再对照附录E的答案,继续学习下一章前,请务必弄懂这些答案。

1.声明Int main( )有何问题?

2.注释可以超过一行吗?

1.查错:输入下面的程序并编译它。它为什么不能通过编译?如何修复?

1: #include <iostream>
2: void main()
3: {
4:      std::Cout << Is there a bug here?";
5: }

2.修复练习1中的错误,然后重新编译、链接并运行它。

3.修改程序清单2.4,以演示减法(使用-)和乘法(使用*)。


相关图书

代码审计——C/C++实践
代码审计——C/C++实践
CMake构建实战:项目开发卷
CMake构建实战:项目开发卷
C++ Templates(第2版)中文版
C++ Templates(第2版)中文版
C/C++代码调试的艺术(第2版)
C/C++代码调试的艺术(第2版)
计算机图形学编程(使用OpenGL和C++)(第2版)
计算机图形学编程(使用OpenGL和C++)(第2版)
Qt 6 C++开发指南
Qt 6 C++开发指南

相关文章

相关课程