◇ 第一章 引言 ◇ 第一章 引言
C++语言是对C语言的扩展,是C语言的超集。C语言是美国贝尔实验室 在1969~1973年开发的,与此同时,还用它开发了UNIX操作系统。C语言又是由B语言衍生而来的,B语言是贝尔实验室的Ken Thompson 在BCPL语言的基础上开发的,并用它编写了第一个UNIX操作系统。BCPL语言是英国剑桥大学 的Martin Richards ,60年代在美国MIT时设计的。 1971年,贝尔实验室的Dennis Ritchie 扩展了B语言(通过增加类型),他称之为NB,即New B。在更改了B语言的结构,并重写了B语言的编译器后,Ritchie称他的新语言为C。1983年,出现了许多C语言的版本,美国国家标准化协会(ANSI) 在1989年出版了标准的C语言,称之为ANSI C。 也是在1983年,贝尔实验室的Bjarne Stroustrup 在C语言的基础上,创建了C++语言,它是为UNIX系统环境设计的。C++语言增强了C语言的能力,使得程序员能够改进编写程序的质量,并易于程序代码的复用。C++语言的ISO标准已在1997年11月被一致通过,1998年8月被正式批准。
C++语言在1980年开始被使用,"C++"这个名字是由Rick Maseitti提出,到1983年夏确定的。C++的创作灵感来源于当时计算机语言多方面的成果,特别是BCPL语言(Basic Combined Programming Language, 它也是C语言的来源之一)和Simula 67语言(以面向对象为核心的语言),同时还借鉴了Algol 68。就如同它的名字表达的那样,C++语言是C语言的一个超集,它是一门混合型的语言,既支持传统的结构化程序设计,又支持面向对象的程序设计,这是C++语言成功流行的一个重要原因。 读者可能产生疑问,既然面向对象的程序设计方法比结构化的程序设计方法先进许多,为什么C++语言仍旧支持后者,而不愿意成为一门纯粹的面向对象的程序设计语言? 实际上,这种做法也是从程序设计语言发展实践中得到的经验。面向对象程序设计的概念提出后,某些公司和机构曾经开发出一些纯面向对象的语言,比如第一个成功的、纯面向对象的程序设计语言的Smalltalk,但是由于广大的程序员不能一下子完全接受面向对象程序设计的思想,不能完全适应面向对象程序设计的技术,这些语言都没有能够广泛的流行起来。事实上,程序员们长期采用结构化的程序设计方法,并从中汲取了许多宝贵经验,形成了巨大的财富,这些财富应该得到继承和发展;而且结构化程序设计方法在小型软件项目的开发设计上仍然很适用,完全否定这种设计方法也是不恰当的。C++作为一门混合型语言,在增加对于面向对象方法的支持的同时,还继承了传统程序设计语言C的优点,克服了其不足之处,使得自身既适用于结构化程序设计,又能满足面向对象程序设计的要求,这就符合广大程序员逐步更新其程序设计观念和方法的要求,因而很快流行起来。总之,对于传统的财富不是完全抛弃,而是继承并发展之,是C++语言成功的重要原因。
C++从C语言发展而来,比C更好,其优点主要包括: (1) 与C语言兼容,既支持面向对象的程序设计,也支持结构化的程序设计。同时,熟悉C语言的程序员,能够迅速掌握C++语言。 (2) 修补了C语言中的一些漏洞,提供更好的类型检查和编译时的分析。使得程序员在C++环境下继续写C代码,也能得到直接的好处。 (3) 生成目标程序质量高,程序执行效率高。一般来说,用面向对象的C++编写的程序执行速度与C语言程序不相上下。 (4) 提供了异常处理机制,简化了程序的出错处理。利用throw、try和catch关键字,出错处理程序不必与正常的代码紧密结合,提高了程序的可靠性和可读性。 (5) 函数可以重载及可以使用缺省参数。重载允许相同的函数名具有不同参数表,系统根据参数的个数和类型匹配相应的函数。缺省参数可以使得程序员能够以不同的方法调用同一个函数,并自动对某些缺省参数提供缺省值。 (6) 提供了模板机制。摸板包括类摸板和函数模板两种,它们将数据类型作为参数。对于具体数据类型,编译器自动生成模板类或模板函数,它提供了源代码复用的一种手段。
C++语言对C语言扩充和增强的几点具体体现 C++在增加面向对象的特征之外,还对C语言进行了扩充和增强。主要的增强点有如下几个: 1. 注释 在C语言块注释的形式 /* Explanation Sentence */ 的基础上,C++语言提供了一种新的单行注释形式: //Explanation Sentence 即用"//"表示注释开始,从该位置直到当前行结束的所有字符都被作为注释。 举个简单的例子:
例1-4: /* 下面的程序段计算从1到100的整数和, 结果记录在变量sum中 */ sum = 0; //变量sum初值置为零 for(i = 1; i <= 100; i++) {//循环体开始 sum += i; // 依次累加i }
2. 更加灵活的变量说明 在传统的C语言中,局部变量的说明必须集中放在执行代码的前面,数据说明语句和执行语句的混合将引起编译错误。而在C++中,可以在程序代码块的任何地方进行局部变量的说明。比如下面的代码在C语言中是不正确的,在C++语言中却可以正常运行。 for(int i = 1; i < = 100; i++); 这样做的好处是使变量的定义和它的使用集中在一起,意义一目了然。 3. 更加严格的函数原型说明 C++摒弃了C语言对函数原型随意简化的方式,这种简化是许多C语言程序错误的根源。C++语言要求编程者为函数提供完整的原型,包括全部参数的类型和返回值得说明。 例如,有字符型和双精度类型两个参数、返回整型值的函数f,原型应该写为: int f(char, double); 而C语言中允许将这个原型写成"f( );"。 在函数原型说明中,参数名可有可无,并且可以和函数定义中的参数名不一致。 4. 增加了函数重载机制 重载是程序语言领域的重要概念。常规语言中最典型的例子是"+、-、×、/"等各种算术运算符的重载,这些符号可以同时用来表示多种类型数据之间的运算,这种对一个名字或一个符号赋予多重意义的情况就叫重载。 C++语言增加了C语言所没有的函数重载机制。对一个函数名可以给出多个函数定义,只要这些定义可以通过参数个数或类型的不同区别开来即可。 C++还允许对系统中预先定义的运算符号进行重载,增加新的定义。这样做的优点是在今后对新定义类型的变量进行运算时,计算公式写起来方便自然。 5. 函数缺省参数 C++中允许函数有缺省参数。所谓缺省,是指函数调用时可以不给出实际的参数值。下面是一个有缺省参数的函数定义的实例:
例1-5: int f(int a, int b=1) { return a*b; }
此后,函数调用f(3,1)和f(3)将返回同样的结果。 6. 更加方便的动态存储分配 C++为了提高内存管理上的灵活性,提供了动态内存分配合释放的操作符new和delete,用来增强C语言中原有的函数malloc()和free(); 7. 增加了内联函数(Inline Function) C++提供了内联函数,用以代替C语言中的宏。宏的处理机构是预处理器而不是编译器,它虽然可以提高效率,但是却不能实现函数调用所拥有的参数类型检查等机制。内联函数不但能够象宏那样节约函数调用时保存现场所需的系统开销,提高程序执行效率,还保留了函数进行参数类型检查的机制;并且C++语言中的宏是不能够存取对象私有成员变量的,但是使用内联函数,则没有这一限制。 8. 输入/输出流机制 C++保留了C语言标准库中各种输入/输出函数,而且提供了一套新的输入/输出机制――流机制。 比如向标准输出输出一个字符串: cout<<"C++ is beautiful!"; 或者由标准输入读一个整数,赋给变量a int a; cin>>a; 流式输入/输出运算符能够根据变量类型自动确定数据交换过程中的转换方式,还可以定义"<<、>>"的重载,方便了编程者自定义类型的数据的输入/输出。 9. 作用域限定运算符:: 作用域限定运算符::用于对当前作用域之外的同名变量进行访问。例如在下面的例子中,我们可以利用::实现在局部变量a的作用域范围内对全局变量a的访问。
例1-6: #include <iostream.h> int a; void main() { float a; a = 3.14; ::a = 6; cout<<"local variable a = "<<a<<endl; cout<<"global variable a ="<<::a<<endl; } 程序执行结果如下: local variable a = 3.14 global variable a = 6
从总体上看,C++程序一般可以分成4个部分,预处理指令、全局说明、程序的主函数和用户自定义的函数,如图1-12所示。下面分别对这几个部分进行介绍。预处理指令
在C++程序中,预处理指令就是源程序中所包括的各种编译命令。所有的预处理指令都以"#"开始进行标识,而且"#"还必须被置于该指令所在程序行的第一列。各种预处理指令在程序编译前执行,其作用是以中间文件的形式向编译器传递一定的信息,并不影响源程序。常用的预处理指令包括预处理包含指令#include;条件预处理指令#ifdef,#ifndef,#define,#else,#endif;宏替换指令#define等等。详细的使用说明可以参考本书的第九章。全局说明 全局说明一般包括一些程序所要使用的全局变量、类说明、用户定义函数的原型说明等。在全局说明段进行说明的变量,其存在和使用是全局性的,在程序运行的整个过程一直存在。主函数 任何一个C++程序都有且只有一个主函数main( ),它可以带参数。main函数的返回值有两种情况:无返回值(返回类型为void)及返回值为整型。若主函数的返回值类型说明为int,即整型的情况,则程序返回值为0,表示程序运行正常结束,返回其他非零整型值表示程序异常返回。用户自定义函数 用户自定义函数是程序员为了实现某些特定的操作而编写的一组代码。当然,程序员完全可以不使用任何函数,而将全部代码都放在main函数中,这样做在语法上没有任何问题。但是,有目的地把某些代码段独立出来,组织成函数的形式,能够体现模块化的思想。 函数可以不带任何参数,也可以无返回值(即返回类型为void),但常用的函数一般都带有一定数目的参数和一个返回值。在函数体内,对这些参数进行一定的运算,返回一个特定类型的数值。通过参数和返回值,函数实现与外界的联系。