第1章 C++语言概述
C++是一种优秀的高级程序设计语言,它是以C语言为基础而逐渐发展起来的。C++语言既保留了传统的结构化程序设计方法,又对流行的面向对象程序设计方法提供了完整的支持。
此外,C++语言还具有许多C语言不支持的新功能和新特性。
C++语言的发展
C++起源于C语言。C语言是\(1972\)年由美国贝尔实验室的Denmis Ritchie根据B语言开发设计出来的。最初,发明C语言的目的是用它来代替汇编语言为小型机 DEC PDP-11 编写 UNIX 操作系统。后来,随着 UINIX 操作系统的推广,C语言被越来越多的程序设计人员了解和使用。到\(20\)世纪\(70\)年代末,C语言已经凭借其如下独有的特点风靡了全世界的程序设计领域:
(1)语言简洁、紧凑,使用灵活、方便。
(2)具有丰富的运算符和数据类型。
(3)可以进行许多低级操作,适合开发系统软件。
(4)程序的运行效率高。
(5)代码的可移植性好。
然而,在C语言流行的同时,也暴露出了它的局限性:
(1)类型检查机制相对较弱,这使得程序中的一些错误不能及时被发现。
(2)缺少支持代码重用的语言结构,因此为一个程序所设计的模块,很难再用于其他程序。
(3)不适合开发大型软件,当程序的规模大到一定程度时,维护工作会变得相当复杂。
为了满足开发大规模程序的需要,\(1980\)年贝尔实验室的Bjarne Stroustrup和他的同事们开始对C语言进行改进和扩充,把Simula 67(一种早期的面向对象语言)中类的概念引入到C语言,并将改进后的C语言称为“带类的C”(C with class)。\(1983\)年夏,“带类的C”被正式命名为“C++”,并于同年7月首次对外发表。\(1985\)年由 Bjarme Stroustrup 编写的《C++程序设计语言》一书出版,这标志着C++1.0版本的诞生。此后,贝尔实验室于\(1989\)年和\(1993\)年分别推出了C++2.0版本和C++3.0版本。表1.1列出了各版本中C++语言所添加的一些新特性。
表1.1 C++语言支持的新特性
版本 | 在C语言基础上添加的新特性 |
---|---|
带类的C | 类和派生类,公有成员和私有成员,构造函数和析构函数,友元,内联函数,赋值运算符的重载 |
C++1.0 | 虚函数,函数运算符的重载,引用,常量 |
C++2.0 | 类的保护成员,多重继承,赋值和初始化的递归定义,抽象类,静态成员函数,const成员函数 |
C++3.0 | 模板,异常,类的嵌套,名字空间 |
经过对C++语言的三次修订后,美国国家标准委员会(ANSI)于 \(1994\) 年制定了 ANSI C++ 标准草案,这个草案最终于 \(1998\) 年被国际标准化组织(ISO)批准为国际标准(ISO/TEC 14882)。C++就是这样在不断地发展和完善中走过了二十多年的历史。至今,它仍然是一种充满活力的程序设计语言。
C++语言的特点
在众多的高级程序设计语言中,C++能够取得成功的原因在于它有着许多与众不同的特点。
1.C++是一种面向对象的程序设计语言
C++语言支持几乎所有的而向对象程序设计特征。可以说,C++语言集中体现了近 \(20\) 年来在程序设计和软件开发领域出现的新思想和新技术,这主要包括:
(1)抽象数据类型。
(2)封装和信息隐藏。
(3)以继承和派生方式实现程序的重用。
(4)以运算符重载和虚函数来实现多态性。
(5)以模板来实现类型的参数化。
2.C++是程序员和软件开发者在实践中创造的
一般的高级程序设计语言是由计算机科学家在科研和教学环境中设计出来的,然而,C++语言却是由从事实际系统开发工作的程序员在实践中创造的。因此,C++往往从编写实际程序的角度出发,为程序员提供了各种实用、灵活、高效的语言特性。正是这些良好的特性使得C++在很多领域,特别是大规模系统程序的开发方面,得到了广泛的应用。目前,许多成功的大型软件都是使用C++编写的。
3.C++是C语言的超集
所谓"C++是C语言的超集”是指C++中包含C语言的全部语法特征。因此,每一个用C语言编写的程序都是一个C++程序。C++语言的设计宗旨就是在不改变C语言语法规则的基础上扩充新的特性。C++与C语言的关系可以用图1.1表示。
实际上,能够很好地兼容C语言正是C++取得成功的原因之一,这是因为:
(1)C++继承了C语言简明、高效、灵活等众多优点。
(2)以前使用C语言编写的大批软件可以不加任何修改,直接在C++开发环境下维护。
(3)C语言程序员只需要学习C++扩充地新特性,就可以很快地使用C++编写程序。
由于具有上述特点,C++已经开始取代C语言,被广泛地应用于各种领域的程序设计工作中。实践表明,对于中型和大型程序的开发工作,使用C++的效果要比C语言好得多。C++正在从软件的可靠性、可重用性、可扩充性、可维护性等方面体现出它的优越性。
面间对象程序设计
面向对象程序设计(Object-Oriented Programming ,简称OOP)是\(20\)世纪\(80\)年代发展起来的一种程序设计方法。它通过模拟现实世界中的事物和关系,利用抽象、分类、归纳等方法来构造软件系统。
在面向对象程序设计出现之前,人们一直采用结构化程序设计(Structured Programming,简称SP)来解决实际问题。结构化程序设计是面向过程的,其主要思想是将功能分解并逐步求精。Pascal语言和C语言都很好地体现了结构化程序设计的思想。
按照结构化程序设计的要求,当需要解决一个复杂的问题时,首先应将它按功能划分为若干个小问题,每个小问题又可以按功能划分为若干个更小的问题,依此类推,直到最低一层的问题较容易用程序实现为止;然后将所有的小问题全部解决并把它们组合起来,复杂的问题就迎刃而解了。然而到了\(20\)世纪\(80\)年代末,随着所要开发程序规模的增大,结构化程序设计的一些缺点就显得越来越突出,这主要表现为:
(1)数据和算法的一致性差。在结构化程序设计中,数据与处理数据的算法是相互分离的。当数据量增大时,程序会变得越来越难理解。如果根据需要而改变某一项数据时,处理此数据的所有算法都要作相应的修改,这就很容易使算法与数据出现不一致的现象。这样的程序是很难修改和维护的。
(2)程序的可重用性差。在电子技术中,要实现某种功能往往有标准的元器件供选择,而不需要自己去设计发明。这就体现出了可重用的思想,即某种通用功能由事先设计好的标准部件来实现。如果在程序设计中可重用性高,那么在很大程度上可以节省人力和物力的浪费。但是结构化程序设计并不支持可重用性,这就使得程序员在开发软件时每次都从零做起,重复着许多同样的工作。
而现实世界中的实际情况恰恰与结构化程序设计思想不同。现实世界中每一种事物都具有一些属性来描述自身的特征,同时具有一些操作来改变自身状态。例如,一辆汽车可以用有型号、颜色、载重量、行驶速度等信息进行描述,这些都是这辆汽车的属性;而开动汽车使它前进、后退、左转、右转等,都是对汽车状态的操作。这样,全部属性和操作的集合就定义了这种汽车的类型。显然,在程序设计中属性对应于数据,操作对应于算法。因此,将数据和处理数据的算法捆绑成一个整体就定义了一种事物的类型。事物类型是一种抽象的概念,只有属于该类型的一个事物实例才是具体可见的,这个实例就叫作“对象”,而事物类型被称为“类”,它们都是面向对象程序设计的基础。
C++是一种面向对象的程序设计语言,它充分支持面向对象思想中的三个主要特征:
1.封装性
封装性是指将数据和算法捆绑成一个整体,这个整体就是对象,描述对象的数据被封装在其内部。如果需要存取数种相被称为信息隐藏。例如,使用者不必知道一台电视机内部电路的具体构造和工作原理,就可以用它来收看电视节目。封装性和数据隐藏从根本上解决了结构化程序设计中数据和算法一致性差的问题。
C++语言通过建立用户定义类型——“类”,来支持封装性和信息隐藏。用户定义的类一旦建立,就可看成是一个完全封装的实体,可以作为一个整体单元来使用。类的内部数据表示被隐藏起来,类的用户不需要知道类内数据的表示方法只需执行类对外提供的算法,就可以完成某项功能。
2.继承性
继承性是指一种事物保留了另一种事物的全部特征,并且具有自身的独有特征。例如,建筑工程师已经设计出了一座普通楼房的图纸,后来又需要设计办公楼和居民楼。这时,可以有两种选择:一是从零开始,分别重新设计办公楼和居民楼;二是在普通楼房图纸的基础上分别添加新的功能,使它成为办公楼和居民楼。工程师当然不想总是从头做起,因为办公楼和居民楼都属于楼房它们都具有楼房的全部特征。既然已经成功地设计出普通楼房的图纸,就不必再费力劳神地重复设计普通楼房了。实际上,工程师在设计具有新功能的楼房时,重复地使用普通楼房的概念。这种思想被称为可重用。
C++语音采用继承来支持重用,程序可以在现有类型的基础上扩展功能来定义新类型。新类型是从现有类型中派生出来的,因此被称为派生类。
3.多态性
多态性是指当多种事物继承自一种事物时,同一种操作在它们之间表现出不同的行为,例如,在一个使用面向对象思想编写的绘图程序中可能含有四种类型的对象,它们分别用于表示抽象概念——形状和具体概念——三角形 、矩形、圆形。其中三角形、矩形、圆形对象都继承了形状对象的全部特征,并且三者都有一个名为“显示”的操作。但当用户对这三种不同的具体形状分别执行“显示”操作时,会在屏幕上得到三种不同的图案。这个例子就说明了多态性。
C++语言种使用函数重载、模板、虚函数等概念来支持多态性。
C++语言的基本符号
组成语言的最小元素是基本符号。汉语中有\(4000\)多个常用单字,英语中有\(26\)个拉丁字母,他们都是组成各自语言的基本符号。同样,作为一种计算机程序设计语言,C++也是由基本负号组成的。
C++语言种的基本符号可以分为\(3\)类:
1.字母
包括大写英文字母 $ A \sim Z $ 和小写英文字母 \(a \sim z\) 共\(52\)个负号。
2.数字
包括 $ 0 \sim 9 $ 共 \(10\)个符号。
3.特殊符号
包括:+ - * / = , . _ : ; ? \ " ' ~ | ! # % & ( ) [ ] { } ^ < >和空格共 $ 30 $ 个符号。
这三类符号共计\(92\)个,它们组成了C++语言的基本符号集合。
C++语言的词汇
基本符号本身一般没有什么含义,而由它们按照一定规则组合成的单词却能表达出某种语义。使用C++语言编写的程序正是由符合规则的单词组成的。那么,什么样的单词才算符合规则呢?答案是:只有下面列出的五类单词才是C++语言中的合法词汇。
关键字
关键字也称为保留字,它是由C++语言本身预先定义好的一类单词。表1.2和表1.3列出了C++的关键字。其中表1.2是 ANSI C 标准规定的\(32\)个关键字,表1.3是 ANSI C++ 标准补充的29个关键字。
表1.2 ANSI C标准规定的关键字
auto | break | case | char | const | continue |
---|---|---|---|---|---|
default | do | double | else | enum | extern |
float | for | goto | if | int | long |
register | return | short | signed | sizeof | static |
struct | switch | typedef | union | unsigned | void |
volatile | while |
表1.3 ANSL C++标准补充的关键字
bool | catch | class | const_cast | delete | dynamic_cast |
---|---|---|---|---|---|
explicit | false | friend | inline | mutable | namespace |
new | operator | private | protected | public | reinterpret_case |
static_cast | template | this | throw | true | try |
typeid | typename | using | virtual | wchar_t |
每个关键字在C++语言中都具有特殊的含义,并实现着一定的功能。所以,不能将上述关键字再当作其他类型的单词使用。
标识符
标识符是用户为程序中各种需要命名的“元素"所起的名字。这些“元素”包括:变量 、符号、常量、函数、函数的参数、结构、类、对象等。标识符的组成要符合定的规则:
jk(1)标识符是一个以字母或下划线开头的,由字母数字、下划线组成的字符串。例如,Hllo
,var2
,myBook
,func_1
,TEST_H
都是合法的标识符;而012
,3var
,A*B
,$ sys
,pay.due
都是非法的标识符。
(2)标识符不能与任意个关键字同名。 例如if
,case
,or
等都不能作为标识符使用。
(3)标识符中的字母区分大小写。例如Abc
和abc
是两个不同的标识符。
(4)标识符不宜过长。C++语言不限制标识符的长度但多数编译器只识别前\(32\)个字符,如果程序中的标识符超过了这个长度,超出的部分被忽略不计。
字面常量
常量是指在程序中固定不变的值。常量一般有两种表示形式,,即符号常量和字面常量。例如在“ pi 等于 \(3.1416\) ”这句话中,pi的值 \(3.1416\) 称为字面常量。C++语言中符号常量的名字就是一个标识符,而字面常量却是一类特殊的单词。字面常量分为整形、浮点型、字符型和字符串型四类。它们的具体命名规则将在第 \(2\) 章中介绍。
运算符
运算符是对程序中的数据进行操作的一类单词。C++语言中运算符的种类非常丰富,其中有:
(1)单字符组成的运算符,例如:+,-,*,/等。
(2)双字符组成的运算符,例如:++,<=,&&,*=,->等。
(3)三个字符组成的运算符,例如:<<=,>>=等。
(4)关键字运算符:new ,delete,sizeof。
各种运算符的具体使用方法将在第\(2\)章中介绍。
标点符号
标点符号是在程序中起分割内容和界定范围作用的一类单词,表1.4列出了C++语言中的标点符号。
表1.4 C++语言的标点符号
标点符号 | 描述 | 标点符号 | 描述 |
---|---|---|---|
(空格) | 语句中各成分之间的分制符 | {(左花括号) | 复合语句的开始标记符 |
;(分号) | 语句的结束符 | }(右花括号) | 复合语句的结束标记符 |
'(单引号) | 字符常量的起止标记符 | //(双斜杠) | 行注释的开始标记符 |
"(双引号) | 字符串常量的起止标记符 | /*(斜杠和星号) | 块注释的开始标记符 |
#(井字号) | 预处理命令的开始标记符 | */(星号和斜杠) | 块注释的结束标记符 |
C++程序的基本框架
对C++语言词汇的介绍,可以从微观上认识C++程序的基本组成单元;而要对C++程序有一个宏观上的总体把握,就要进一步了解程序的基本框架。为便于理解,先来看一个最简单的C++程序。
例1.1 一个最简单的C++程序
//ex1_1.cpp
#include<iostream>
int main()
{
std::cout<<"This is a simple C++ program.\n";
return 0;
}
此程序的运行结果是在屏幕上显示:
This is a simple C++ program.
上述程序虽然只有\(7\)行,但它却包含了每一个C++程序都要具备的几个基本组成部分。由于这是本书中第一个完整的C++程序,这里对它进行逐行解释:
第一行:// exl_1. CPP
这是一个注释行。注释是程序编写者为读者作的一种说明,有助于提高程序的可读性。C++中提供了“行”和“块”两种注释方法。行注释的内容从双斜杠//
开始到本行末尾结束,例如,// exl_1.cpp
就是行注释;块注释的内容从符号/*
开始到符号*/
结束,例如:
/* only one line */
和
/* this is the first line
this is the second line
this is the third line */
都是块注释。本行注释中的内容为源程序文件的名称一一“ex1_1. cpp”,通常C++源程序文件以 .cpp 为扩展名。
第二行: #inelude<iostream>
这是一条预处理命令。C++中每一个以符号#
开头的行都是预处理命令。使用预处理命令可以更好地进行程序的组织。本行预处理命令#include<iostream>
的作用是将头文件iostream
的内容加到程序中。iostream
是一个C++标准头文件,其中定义了一些输入输出流对象。
第三行:int main()
本行是主函数的声明。主函数是所有C++程序开始执行的人口。无论主函数处于程序中的什么位置,其中的代码总是最先被执行。按照C++语言的规定,每个程序都必须有且仅有一个主函数,主函数的名称必须为main
。
main
前面的int
表示主函数main
将返回一个int
类型的值。int
代表整型值,它是C++中的一个基本数据类型。
跟在main
后面的圆括号()
说明它是一个函数。在C++中所有的函数名称后面都紧跟着一对圆括号,其中可以没有内容(即没有函数的参数,例如本行),也可以包含函数的参数。
第四、七行:在主函数main的声明之后用花括号{}
括起来的是函数主体部分。
第五行:std::cout<<"This is a simple C++ program.\n";
本行是一条C++语句,它完成了此程序的主要功能,即向屏幕上输出一行字符串。cout
是C++中的标准输出流对象,它通常代表计算机的屏幕。cout
在标准头文件iosteam
中被声明
(注:标识符
cout
位于std
名字空间中,须用前缀std::
进行修饰),因此要使用它就必须先包含此文件(见程序的第2行)。
<<
是输出操作符,功能是将它右边的内容输出到它左边的指定设备上。这里,要输出的内容是用双引号括起来的字符串This is a simple C++ program.\n
,其中的字符\n
是换行符。本行末尾的分号;
表示这条语句的结束。在C++中所有的语句都要以分号结束。
第六行:return 0;
本行是 return
语句,它的功能是使主函数main
结束并将整数\(0\)返回给运行此程序的操作系统。返回整数\(0\)表示程序在执行过程中没有发生任何错误而正常结束。
实际上,按照C++标准,本行是可以省略的。如果在主函数main
中不写return 0;
语句,程序正常结束时也会自动向操作系统返回\(0\)。
C++程序的开发过程
开发一个C++程序的过程通常包括编辑、编译、连接、运行和调试等步骤。目前有许多软件产品可以帮助我们完成C++程序的开发。例如,在Windows平台下有 Microsoft公司的VisualC++和Borland 公司的C++ Builder;在 Linux平台下有GUN 的gec和 gdb等。本节将以Microsoft公司的Visual C++6.0(简称VC6)为工具来介绍C++程序的开发过程。关于使用VC6集成开发环境编写标准C++程序的具体方法请参见本书附录A。
编辑
编辑是C++程序开发过程的第一步,它主要包括程序文本的输入和修改。任何一种文本编辑器都可以完成这项工作。在VC6集成开发环境中,用户可以使用编辑窗口来进行C++程序的编辑工作。VC6的编辑窗口是专门为编辑C++程序而设计的,它提供了包括语法亮色、调用提示、自动缩进、查找和替换等在内的一系列功能,使用起来十分方便。
当用户完成了C++程序的编辑时,应将输人的程序文本保存为以 .cpp 为扩展名的文件(保存C++头文件时应以 .h 为扩展名)。
编译
C++是一种高级程序设计语言,它的语法规则与汇编语言和机器语言相比更接近人类自然语言(如英语)的习惯。然而,计算机能够“看”懂的唯一语言是机器指令。因此,当我们要让计算机“看”懂一个C++程序时,就必须使用一种叫作“编译器”的工具,将这个C++程序“翻译”成机器指令。
编译器所做的工作实际上是一种由高级语言到机器指令的等价变换。用户提供给编译器的输入信息称为源程序代码,它是用某种高级语言编写的程序文本。编译器对源程序代码进行一系列处理后最终产生的输出结果称为目标代码,它是某种计算机的机器指令,并且在功能上与源程序代码完全等价。保存源程序代码和目标代码的文件分别称为源程序文件和目标文件。由源程序文件到目标文件的转换过程就称为编译。
实际上,在进行编译之前还要完成一项称为“预处理”的工作。它的目的是根据程序中的预处理命令对源程序代码做出相应的处埋,或为编译器提供一些提示信息。程序中的注释在预处理过程中被删除掉,因此注释中的内容除了方便阅读之外不会对程序运行产生任何影响。
在VC6集成开发环境中,用户可以使用编译(Compile)命令将一个以 .cpp 为扩展名的C++源程序文件转换成一个以 .obj 为扩展名的目标文件。如果一个C++程序由多个源程序文件组成,应将它们分别进行编译形成多个目标文件。
连接
要将编译器产生的目标代码变成可执行程序还需要最后一个步骤——连接。连接工作是由“连接器"完成的,它将编译后产生的一个或多个目标文件与程序中用到的库文件连接起来,形成一个可以在操作系统中直接运行的可执行程序(如 Windows下的 .exe 文件)。
在VC6集成开发环境中,用户可以使用生成(Build )命令来进行目标文件的连接工作。另外,在源程序文件没有被编译的情况下直接使用此命令,可以使编译和连接工作一起完成。
运行和调试
如果源程序文件中存在着语法错误或连接错误,编译器和连接器会分别给出相关的错误信息。这时需要重新编辑源程序文件,改正其中的错误,再一次进行编译和连接,重复此过程直到错误信息不再出现为止。
在编译和连接工作成功地完成之后可以运行得到的可执行程序,观察程序是否符合期望的运行结果。在VC6集成开发环境中,用户可以使用执行(Execute)命令来运行程序。
如果程序的运行结果不是我们所期望的,说明源程序文件中存在着语义错误。这时,需要使用调试器对可执行程序进行跟踪调试来查找错误发生的原因。在VC6集成开发环境中,用户可以很方便地进入调试状态,对程序进行设置断点、单步执行、观察变量等操作。
一般地,开发一个C++程序的整体流程可用图1.2表示。
本章小结
本章内容是C++语言的概述。C++是以C语言为基础发展起来的一种高级程序设计语言。C++语言的一个重要特点是它对面向对象程序设计提供了完整的支持。封装性、继承性和多态性是面向对象思想的主要特征。
一定数量的基本符号是组成C++语言的最小元素。关键字、标识符、字面常量、运算符和标点符号是组成C++语言的词汇。
开发一个C++程序的步骤通常包括编辑、编译、连接、运行和调试。
习题1
选择题
1.C++语言是以语言为____语言为基础逐渐发展演变而成的一种程序设计语言。
A) Pascal
B) C
C) B
D) Simula 67
2.下列关于C++与C语言关系的描述中错误的是____。
A) C++是C语言的超集
B) C++对C语言进行了扩充
C) C++包含C语言的全部语法特征
D) C++与C语言都是面向对象的程序设计语言
3.面向对象程序设计思想的主要特征中不包括____。
A) 继承性
B) 功能分解,逐步求精
C) 封装性和信息隐藏
D) 多态性
4.下列关于C++关键字的说法中正确的是____。
A) 关键字是用户为程序中各种需要命名的“元素”所起的名字
B) 关键字是对程序中的数据进行操作的一类单词
C) 关键字是在程序中起分割内容和界定范围作用的一类单词
D) 关键字是C++中预先定义并实现一定功能的一类单词
5.下列字符串中可以用作C++标识符是____。
A) _123
B) foo~bar
C) case
D) 3var
6.下列C++标点符号中表示一条语句结束的是____。
A) #
B) ;
C) //
D) {
7.下列C++标点符号中表示一条预处理命令开始的是
A) #
B) ;
C) //
D) }
8.每个C++程序都必须有且仅有一个____。
A) 函数
B) 预处理命令
C) 主函数
D) 语句
填空题
1.组成C++语言的基本符号包括:字母、____和特殊符号。
2.C++语言的标识符是以字母或____开头的,由字母、数字、____组成的字符串。
3.cout
是C++中标准输出流对象,它通常代表____。
4.一个C++程序的开发步骤通常包括编辑、____、连接、运行和调试。
编程题
1.请将下列程序补充完整,使其运行结果是在屏幕上输出字符串Hello,world.
。
#include<iostream>
int main()
{
return 0;
}
2.请指出并改正下列程序中存在的三点错误。
main()
{
std::cout<<"This is a string.\n"
return 0;
}
习题参考答案
选择题
1.B
2.D
3.B
4.D
5.A
6.B
7.A
8.C
填空题
1.数字
2.下划线;下划线
3.计算机的屏幕
4.编译
编程题
1.完整代码如下:
#include<iostream>
int main()
{
std::cout<<"Hello,world.";
return 0;
}
2.正确代码如下:
#include<iostream>
int main()
{
std::cout<<"This is a string.\n";
return 0;
}
错误1:没有使用头文件iostream
;
错误2:main
主函数没有声明类型;
错误3:std::cout<<"This is a string.\n"
行末没有加分号;
;