第9章 C++程序设计初步 9.1 C++的特点 9.2 最简单的C++程序 9.3 C++的输入输出 9.4 函数的重载

Slides:



Advertisements
Similar presentations
說 劍 《莊子‧雜篇》─ 第 一 組 賴泊錞 謝孟儒 張維真 羅苡芸
Advertisements

第一章 C语言概述 计算机公共教学部.
第九章 字串 (String).
“08高考化学学业水平(必修科目)测试的命题和教学对策研究”
电在我们日常生活、现代化社会中的应用: 电 是 什 么?.
C++程序设计 主讲:王兴波教授 1.
成才之路 · 语文 人教版 · 必修2 路漫漫其修远兮 吾将上下而求索.
高级语言程序设计 主讲人:陈玉华.
第5章 函数与预处理 《 C语言程序设计》 (Visual C++ 6.0环境) 本章导读
走向C++之路 WindyWinter WindyWinter感谢诸位前来捧场。
Chap 18 類別與物件 夫有土者,有大物也。有大物者,不可以物。 物而不物,故能物物。 明乎物物者之非物也,豈獨治天下百姓而已哉!
C++程序设计 第二讲 清华大学软件学院.
补充内容 结构体 概述 定义结构体类型和定义结构体变量 结构体变量的引用 结构体变量的初始化 指针与结构体 用typedef定义类型的别名.
第4章 函数与预处理 4.1 概述 4.2 定义函数的一般形式 4.3 函数参数和函数的值 4.4 函数的调用 *4.5 内置函数
编译原理与技术 类型检查 2018/11/21 《编译原理与技术》-类型检查.
C++语言程序设计 C++语言程序设计 第六章 指针和引用 第十一组 C++语言程序设计.
新世纪计算机专业系列教材 数据结构 C++实现 第一章 缪淮扣 顾训穰 沈 俊 编著 科 学 出 版 社.
C++ 程式設計— 語言簡介 台大資訊工程學系 資訊系統訓練班.
第七章 函数 目录 有参的加法函数的开发 函数定义的一般形式 函数参数和函数的值 函数的调用
C++语言程序设计 C++语言程序设计 第四章 数组及自定义数据类型 C++语言程序设计.
授课老师:龚涛 信息科学与技术学院 2018年3月 教材: 《Visual C++程序员成长攻略》 《C++ Builder程序员成长攻略》
Object-Oriented Programming in C++ 第一章 C++的初步知识
第三章 C++中的C 面向对象程序设计(C++).
第12章 從C到C++語言 12-1 C++語言的基礎 12-2 C++語言的輸出與輸入 12-3 C++語言的動態記憶體配置
C语言程序设计 李祥.
第一章 C++编程简介 丘志杰 电子科技大学 计算机学院 软件学院.
第二章 C++对C 在非面向对象方面的改进 更简洁,更安全.
C++语言程序设计 第二章 C++简单程序设计.
第八章 使用指针.
谭浩强 编著 中国高等院校计算机基础教育课程体系规划教材 C++程序设计.
第十章 指针.
第三章 数据类型、运算符与表达式.
第1章 概述 本章要点: C语言程序结构和特点 C语言程序的基本符号与关键字 C语言程序的编辑及运行 学习方法建议:
C++ 程式設計 基礎篇 張啟中 Chang Chi-Chung.
第十章 用户自定义数据类型 目录 学生信息管理系统的开发 结构体数据类型的概述 结构体变量的使用 结构体数组
Name1..hour //加班時數 name2..hour //請假時數
第1讲 C语言基础 要求: (1) C程序的组成 (2) C语言的标识符是如何定义的。 (3) C语言有哪些基本数据类型?各种基本数
C++语言程序设计 C++语言程序设计 第五章 函数 第十一组 C++语言程序设计.
C语言大学实用教程 第5章 函数与程序结构 西南财经大学经济信息工程学院 刘家芬
第2章 数据类型及表达式 本章导读 本章主要知识点 《 C语言程序设计》 (Visual C++ 6.0环境)
第三章 C++的语句和简单的程序设计 主要内容:
第 二 章 数据类型、运算符与表达式.
C程序设计.
Oop8 function函式.
第11章 從C到C++語言 11-1 C++語言的基礎 11-2 C++語言的資料型態與運算子 11-3 C++語言的輸出與輸入
第三章 数据抽象.
C程序设计.
第一章 C语言概述 教师:周芸.
C++语言程序设计教程 第2章 数据类型与表达式 第2章 数据类型与表达式 制作人:杨进才 沈显君.
C++程式設計入門 變數與運算子 作者:黃建庭.
第2章 数据类型、运算符与表达式 本章要点: 基本数据类型 常量和变量 算术运算符和算术表达式 关系运算符和关系表达式
第7章 程序的结构 四、生存期与存储属性 五、extern关键字与外部连接属性 六、static关键字与内部连接属性.
第2章 基本数据及其运算 本章学习的目标: 1、掌握基本数据的各种表示,基本数据常数的书写方法;
第二章 类型、对象、运算符和表达式.
C/C++基礎程式設計班 C++: 物件的使用、參考、重載函式 講師:林業峻 CSIE, NTU 3/28, 2015.
第1章 C++面向对象程序设计要点 1.1 函数和函数参数 1.2 输入输出   1.3 类 1.4 抽象类型和模板.
C程序设计.
第 3 章 类的基础部分 陈哲 副教授 南京航空航天大学 计算机科学与技术学院.
挑戰C++程式語言 ──第9章 函數.
第四章 函数 丘志杰 电子科技大学 计算机学院 软件学院.
第十二章 位运算.
《数据结构与算法设计》第一部分 面向对象的C++程序设计基础.
第三章 高级函数特性.
C/C++基礎程式設計班 C語言入門、變數、基本處理與輸入輸出 講師:林業峻 CSIE, NTU 3/7, 2015.
變數與資料型態  綠園.
第六章 复合数据类型 指针的声明与使用 数组的声明与使用 指针与数组的相互引用 字符串及相关库函数 new与delete
安排座位.
第十二章 C与C C转入C++时不需改变的内容 12.2 C转入C++的一些与类无关的 新特性
C++语言程序设计 C++语言程序设计 第二章 基本数据类型与表达式 第十一组 C++语言程序设计.
Presentation transcript:

第9章 C++程序设计初步 9.1 C++的特点 9.2 最简单的C++程序 9.3 C++的输入输出 9.4 函数的重载 9.4 函数的重载 9.5 带缺省参数的函数 9.6 变量的引用类型5 9.7 内置函数 9.8 作用域运算符 9.9 动态分配/撤销内存的运算符new和delete 9.10 小结

9.1 C++的特点 C语言是结构化和模块化的语言,它是面向过程的。在处理较小规模的程序时,程序员用C语言较得心应手。但是当问题比较复杂、程序的规模比较大时,结构化程序设计方法就显出它的不足。C程序的设计者必须细致地设计程序中的每一个细节,准确地考虑到程序运行时每一时刻发生的事情,例如各个变量的值是如何变化的,什么时候应该进行哪些输入,在屏幕上应该输出什么等。这对程序员的要求是比较高的,如果面对的是一个复杂问题,程序员往往感到力不从心。当初提出结构化程序设计方法的目的是解决软件设计危机,但是这个目标并未完全实现。

为了解决软件设计危机,在20世纪80年代提出了面向对象的程序设计(Object-Oriented programming,简称OOP) ,在这种形势下,C++应运而生。C++是由贝尔实验室的Bjarne Stroustrup博士及其同事在C语言的基础上开发成功的。C++保留了C语言原有的所有优点,增加了面向对象的机制。C++与C完全兼容,用C语言写的程序可以不加修改地用于C++。从C++名字可以看出它是对C的扩充,是C的超集。它既可以用于结构化程序设计,又可用于面向对象的程序设计,因此它是一个功能强大的混合型的程序设计语言。

使用C++必须事先安装C++编译系统,在DOS系统下可以使用Turbo C++或Borland C++。C源程序的后缀一般为 使用C++必须事先安装C++编译系统,在DOS系统下可以使用Turbo C++或Borland C++。C源程序的后缀一般为.c,而C++的后缀一般为.cpp(为C plus plus的缩写,即C++)。在Borland C++开发环境中,既可以使用C语言,也可以使用C++语言。它有两个编译系统,根据源程序文件名的后缀是.c还是.cpp来决定使用哪个编译系统。

如上所述,面向对象程序设计方法主要是解决大型软件的设计问题。只有编写过大型程序的人才会体会到C的不足和C++的优点。C++是一种大型语言,其功能、概念和语法规定都比较复杂,要深入掌握它需要花较多的时间,尤其是需要有较丰富的实践经验。用C++编程的主要是软件专业人员。学校里一般专业的程序设计课程任务主要是进行程序设计的基本训练,因此,我们认为当前对大多数学生来说,应先掌握好C语言程序设计。有了C语言的基础在需要时再学习C++不会太困难。为了使读者对C++有初步的了解,以便为今后学习C++打下基础,我们在进行本书的修订时特地增加了第14章和第15章,介绍C++的初步知识。

C++对C的“增强”,表现在两个方面: (1) 在原来面向过程的机制基础上,对C语言的功能做了不少扩充。 (2) 增加了面向对象的机制。 本章介绍C++对C功能的扩充。第15章介绍有关面向对象的内容。

9.2 最简单的C++程序 例9.1 输出一行字符。 本程序和以前见过的C程序有什么不同? #include <stdio.h> #include <iostream.h> /* 本程序的作用是输出一行字符 */ void main( ) { printf("This is a c++ program.\ n"); cout <<" This is a c++ program.\ n" ; //本行输出一行字符 } 本程序和以前见过的C程序有什么不同?

(1) 在C++程序中一般习惯在主函数main前面加了一个类型声明符void,表示main函数没有返回值。 (3) 除了可以用printf函数输出信息外,还可以用cout进行输出。cout要与运算符<<配合使用,程序中cout的作用是将<<运算符右侧的内容送到输出设备中输出。

(4) 使用cout需要用到头文件iostream.h,在程序的第一行用#include命令将该头文件“包含”进来。 程序运行时输出:This is a c++ program. This is a c++ program.可以看到程序中最后两个语句的作用相同,都是输出This is a c++ program.。

9.3 C++的输入输出 在C语言中文件不是由记录构成的。对文件的存取是以字节为单位的,对一个C文件的输入和输出是一个字节流。输入和输出的数据流的开始和结束只受程序控制而不受物理符号(如回车换行符)的控制。这种文件称为流式文件。在输入操作中,字节从输入设备流向内存,在输出操作中,字节从内存流向输出设备。C++为了方便使用,除了可以利用printf和scanf函数进行输出和输入外,还增加了标准输入输出流cout和cin。cout是由c和out两个单词组成的,代表C++的输出流,cin是由c和in两个单词组成的,代表C++的输入流。它们是在头文件iostream.h中定义的。在键盘和显示器上的输入输出称为标准输入输出,标准流是不需要打开和关闭文件即可直接操作的流式文件。

C++预定义的标准流如表9.1所示。 表9.1 流名 含义 隐含设备 cin 标准输入 键盘 cout 标准输出 屏幕 cerr 标准出错输出 clog cerr的缓冲形式

9.3.1 用cout进行输出 cout必须和输出运算符<<一起使用。<< 在这里不作为位运算的左移运算符,而是起插入的作用,例如:cout<<"Hello!\n";的作用是将字符串“Hello!\n” 插入到输出流cout中,也就是输出在标准输出设备上。 也可以不用\n控制换行,在头文件iostream.h中定义了控制符endl代表回车换行操作,作用与\n相同。endl的含义是end of line,表示结束一行。 可以在一个输出语句中使用多个运算符<< 将多个输出项插入到输出流cout中,<<运算符的结合方向为自左向右,因此各输出项按自左向右顺序插入到输出流中。例如:

注意:每输出一项要用一个<< 符号。不能写成 cout<<a,b,c,"A"; 形式。 for (i=1; i<=3;i++) cout<<"count="<<i<<endl; 输出结果为: count=1 count=2 count= 3 注意:每输出一项要用一个<< 符号。不能写成 cout<<a,b,c,"A"; 形式。 用cout和<< 可以输出任何类型的数据,如: float a=3.45; int b=5; char c=′A′; cout<<"a="<<a<<","<<"b="<<b<<","<<"c="<<c<<endl;

输出结果为 a=3.45,b=5,c=A 可以看到在输出时并未指定数据的类型(如实型、整型),系统会自动按数据的类型进行输出。这比用printf函数方便,在printf函数中要指定输出格式符(如%d,%f,%c等)。 如果要指定输出所占的列数,可以用控制符setw设置(注意:若使用setw,必须包含头文件 iomanip.h),如setw(5) 的作用是为其后面一个输出项预留5列,如输出项的长度不足5列则数据向右对齐,若超过5列则按实际长度输出。如将上面的输出语句改为:cout<<"a="<<setw(6)<<a<<endl<<"b="<<setw(6)<<b<<endl<<"c="<<setw(6)<<c<<endl;

在C++中将数据送到输出流称为“插入”(inserting) ,或“放到”(putting) 。<< 常称为“插入运算符”。 输出结果为 a=3.45 b=5 c=A 在C++中将数据送到输出流称为“插入”(inserting) ,或“放到”(putting) 。<< 常称为“插入运算符”。

cin要与 >> 配合使用。例如: 输入流是指从输入设备向内存流动的数据流。标准输入流cin是从键盘向内存流动的数据流。用>> 运算符从输入设备键盘取得数据送到输入流cin中,然后送到内存。在C++中,这种输入操作称为“提取”(extracting) 或“得到”(getting) 。>> 常称为“提取运算符”。 cin要与 >> 配合使用。例如: int a; float b; cin>>a>>b; //输入一个整数和一个实数。注意不要写成cin>>a,b; 可以从键盘输入: 20 32.45 (数据间以空格分隔)

a和b分别获得值20和32.45。用cin和>> 输入数据同样不需要在本语句中指定数据类型(用scanf函数输入时要根据数据类型指定输入格式符,如%d,%c等)。 例9.2 cin与cout一起使用。 #include <iostream.h> void main( ) {cout<<"please enter your name and age:"<<endl; char name[10]; int age; cin>>name; cin>>age; cout<<"your name is "<<name<<endl; cout<<"your age is "<< age<<endl; }

运行情况如下: please enter your name and age: Wang-li↙ 19 ↙ your name is Wang-li your age is 19 程序中对变量的定义放在执行语句之后。C语言是不允许这样的,它要求声明部分必须在执行语句之前。而C++允许对变量的声明放在程序的任何位置(但必须在使用该变量之前)。这是C++对C限制的放宽。 C++为流输入输出提供了格式控制,如:dec(用十进制形式),hex(用十六进制形式),oct(用八进制形式), 还可以控制实数的输出精度等。

9.4 函 数 的 重 载 在上一节用到了插入运算符<< 和提取运算符>>。 这两个运算符本来是左移运算符和右移运算符,现在把它作为输入输出运算符。即允许一个运算符用于不同场合,有不同的含义,这就叫运算符的“重载”(overloading),即重新赋予它新的含义。其实就是“一物多用”。 函数也可以重载。用C语言编程时,有时会发现有几个不同名的函数,实现的是同一类的操作。例如要求从3个数中找出其中最大者,而这3个数的类型事先不确定,可以是整数、实数或长整数。程序设计者必须分别设计出3个函数,其原型为:

int max1(int a, int b, int c); (求3个整数中的最大者) float max2(float a, float b, float c); (求3个实数中的最大者) long max3(long a, long b, long c); (求3个长整数中的最大者) C语言规定在同一作用域(如同一文件模块中)中不能有同名的函数,因此3个函数的名字不相同。 C++允许在同一作用域中用同一函数名定义多个函数,这些函数的参数个数和参数类型不同。这就是函数的重载,即一个函数名多用。 对上面的问题可以编写如下的C++程序。 例9.3 求3个数中最大的数(分别考虑整数、实数、长整数的情况)。

#include <iostream.h> int max(int a, int b, int c) //求3个整数中的最大者 { if (b>a) a=b; if (c>a) a=c; return a; } float max(float a,float b, float c) //求3个实数中的最大者 long max(long a,long b,long c) //求3个长整数中的最大者 return a; } void main( ) {int a,b,c; float d,e,f; long g,h,i; cin>>a>>b>>c; cin>>d>>e>>f; cin>>g>>h>>i; int m; m= max(a,b,c); //函数值为整型 cout <<"max-i="<<m<<endl; float n; n=max(d,e,f); //函数值为实型

main函数3次调用max函数,每次实参的类型不同。系统会根据实参的类型找到与之匹配的函数,然后调用该函数。 cout<<"max-f="<<n<<endl; long int p; p=max(g,h,i); //函数值为长整型 cout<<"max-l="<<p<<endl; } 运行情况如下: 85-6↙ 56.990.76543.1↙ 67543-56778123↙ max-i=8 (3个整数的最大值) max-f=90.765 (3个实数的最大值) max-l=78123 (3个长整数的最大值) main函数3次调用max函数,每次实参的类型不同。系统会根据实参的类型找到与之匹配的函数,然后调用该函数。 上例3个max函数的参数个数相同而类型不同。参数个数也可以不同,见下例。

例9.4求n个整数中的最大数。n的值为2和3。 运行情况如下: #include <iostream.h> int max(int a, int b, int c) //求3个整数中的最大者 { if (b>a) a=b; if (c>a) a=c; return a; } int max(int a, int b) //求两个整数中的最大者 { if (a>b) return a; else return b;}void main( ) {int a=7,b=-4,c=9; cout<<max(a,b,c)<<endl; //输出3个整数中的最大者 cout<<max(a,b)<<endl; //输出两个整数中的最大者 } 运行情况如下: 9 7

两次调用max函数的参数个数不同,系统会根据参数的个数找到与之匹配的函数并调用它。 参数的个数和类型可以都不同。应当注意:重载函数的参数个数或类型必须至少有一者不同,函数返回值类型可以相同也可以不同。但不允许参数个数和类型都相同而只有返回值类型不同,因为系统无法从函数的调用形式上判断哪一个函数与之匹配。

9.5 带缺省参数的函数 一般情况下,实参个数应与形参个数相同。C++允许实参个数与形参个数不同。办法是在形参表列中对一个或几个形参指定缺省值(或称默认值)。例如某一函数的首部可用如下形式: void fun(int a, int b, int c=100) 在调用此函数时如写成fun(2,4,6),则形参a,b,c的值分别为2,4,6(这是与过去一样的)。如果写成fun(2,4) ,即少写了最后一个参数,由于在函数定义时已指定了c的缺省值为100,因此a,b,c的值分别为2,4,100。请注意:赋予缺省值的参数必须放在形参表列中的最右端。例如: void f1(float a, int b, int c=0, char d=′a′) (正确) void f2(float a, int c=0, char d=′a′, int b) (不正确)

利用这一特性,可以使函数的使用更加灵活。例如例9.4求两个数或3个数中的最大数。也可以不用重载函数,而将函数max的首行写成 int max(int a, int b, int c=-32768) 如果只想从两个数中找大者,则可以在调用时写成max(100,675) ,c的值自动取-32768,由于-32768是最小整数,因此从100, 675, -32768中选大者和从100, 675中选大者的结果是一样的。 注意:不要同时使用重载函数和缺省参数的函数,因为当调用函数时少写一个参数,系统无法判定是利用重载函数还是利用缺省参数的函数,会发生错误。

9.6 变量的引用类型 9.6.1 引用的概念 “引用”(reference)是C++的一种新的变量类型,是对C的一个重要扩充。它的作用是为一个变量起一个别名。假如有一个变量a,想给它起一个别名b,可以这样写: int a; int &b=a; 这就声明了b是a的“引用”,即a的别名。经过这样的声明后,使用a或b的作用相同,都代表同一变量。注意:在上述声明中,&是“引用声明符”, 并不代表地址。不要理解为“把a的值赋给b的地址”。

声明引用并不另开辟内存单元,b和a都代表同一变量单元。在声明一个引用型变量时,必须同时使之初始化,即声明它代表哪一个变量。 在声明一个变量的引用后,在本函数执行期间,该引用一直与其代表的变量相联系,不能再作为其他变量的别名。下面的用法不对: int a1,a2; int &b=a1; int &b=a2;(企图使b变成a2的引用(别名)是不行的)

9.6.2 引用的简单使用 通过下面的例子可以了解引用的简单使用。 例9.5 了解引用和变量的关系。 9.6.2 引用的简单使用 通过下面的例子可以了解引用的简单使用。 例9.5 了解引用和变量的关系。 #include <iostream.h> #include <iomanip.h> void main( ) {int a=10; int &b=a; //声明b是a的引用 a=a*a; //a的值变化了,b的值也应一起变化 cout<<a<<setw(6)<<b; b=b/5; //b的值变化了,a的值也应一起变化 cout<<b<<setw(6)<<a; }

a的值开始为10,b是a的引用,它的值当然也应该是10,当a的值变为100(a a的值开始为10,b是a的引用,它的值当然也应该是10,当a的值变为100(a*a的值)时,b的值也随之变为100。在输出a和b的值后,b的值变为20,显然a的值也应为20(见图9.1)。运行记录如下: 100 100 20 20 图9.1

9.6.3 引用作为函数参数 有了变量名,为什么还需要一个别名呢?C++之所以增加“引用”, 主要是把它作为函数参数,以扩充函数传递数据的功能。 在C语言中,函数的参数传递有以下两种情况。 (1) 将变量名作为实参。这时传给形参的是变量的值。传递是单向的,在执行函数期间形参值发生变化并不传回给实参,因为在调用函数时,形参和实参不是同一个存储单元。下面的程序无法实现两个变量的值互换。

例9.6 错误的程序。 #include <iostream.h> void swap(int a, int b) {int temp; temp=a; a=b; b=temp; //实现a和b的值互换 } void main( ) {int i=3,j=5; swap(i,j); cout<<i<<","<<j<<endl; //i和j的值未互换

输出i和j的值仍为3和5。见图9. 2示意。图9. 2(a) 表示调用函数时的数据传递,图9 输出i和j的值仍为3和5。见图9.2示意。图9.2(a) 表示调用函数时的数据传递,图9.2(b) 是执行swap函数体后的情况,a和b值的改变不会改变i和j的值。 为了解决这个问题,在第10章介绍了传递变量地址的方法。 图9.2

(2) 传递变量的指针。使形参得到一个变量的地址,这时形参指针变量指向实参变量单元。见例9.7。 例9.7 使用指针变量作形参,实现两个变量的值互换。 #include <iostream.h> void swap(int *p1, int *p2) {int temp; temp=*p1; *p1= *p2; *p2=temp; } void main( ) {int i=3,j=5; swap(&i,&j); cout<<i<<","<<j<<endl;

形参与实参的结合见图9. 3示意。调用函数时把变量i和j的地址传送给形参p1和p2(它们是指针变量),因此. p1和i为同一内存单元, 形参与实参的结合见图9.3示意。调用函数时把变量i和j的地址传送给形参p1和p2(它们是指针变量),因此*p1和i为同一内存单元,*p2和j为同一内存单元,图9.3(a) 表示刚调用swap函数时的情况,图9.3(b) 表示执行完函数体语句时的情况。 图9.3

显然,i和j的值改变了。 这种方法其实也是采用“值传递”方式,向一个指针变量传送一个地址。然后再通过指针变量访问有关变量。这样做能得到正确结果,但是在概念上“兜了一个圈子” ,不那么直截了当。在PASCAL语言中有“值形参”和“变量形参”(即var形参) ,对应两种不同的传递方式,前者采用值传递方式,后者采用地址传递方式(传送的是变量的地址而不是变量的值,使形参指向一个变量)。在C语言中,只有“值形参”而无“变量形参”,全部采用值传递方式。C++把引用型变量作为函数形参,就弥补了这个不足。 C++提供了向函数传递数据的第三种方法,即传送变量的别名。

例9.8 利用“引用形参”实现两个变量的值互换。 #include <iostream.h> void swap(int &a, int &b) {int temp; temp=a; a=b; b=temp; } void main( ) {int i=3,j=5; swap(i, j); cout<<"i="<<i<<" "<<"j="<<j<<endl; 输出结果为 i=5 j=3

在swap函数的形参表列中声明变量a和b 是整型的引用变量(和其他变量一样,既可以在函数体中声明变量的类型,也可以在定义函数时在形参表列中声明变量的类型)。图9.4请注意:在此处&a不是“a的地址”,而是指“a是一个引用型变量”。 但是此时并未对它们初始化,即未指定它们是哪个变量的别名。当main函数调用swap函数时由实参把变量名传给形参。i的名字传给引用变量a,这样a就成了i的别名。同理,b成为j的别名。a和i代表同一个变量,b和j代表同一个变量。在swap函数中使a和b的值对换,显然,i和j的值同时改变了(见图9.4示意,其中(a)是刚开始执行swap函数时的情况,(b)是执行完函数体语句时的情况)。在main函数中输出i和j已改变了的值。

实际上,实参传给形参的是变量的地址,也就是使形参a具有变量i的地址,从而使a和i共享同一单元。为便于理解,我们说把变量i的名字传给引用变量a,使a成为i的别名。请注意这种传递方式和使用指针变量作形参时有什么不同?分析例9.8(对比例9.7),可以发现:① 不必在swap函数中设立指针变量,指针变量要另外开辟内存单元,其内容是地址。而引用变量不是一个独立的变量,不单独占内存单元,在本例中其值为一整数。② 在main函数中调用swap函数时实参不必在变量名前加&以表示地址。这种传递方式相当于PASCAL语言中的“变量形参”,系统传送的是实参的地址而不是实参的值。显然,这种用法比使用指针变量简单、直观、方便。

当读者看到&a这样的形式时,怎样区别是声明引用变量还是取地址的操作呢?请记住,当&a的前面有类型符时(如int &a),它必然是对引用的声明;如果前面无类型符(如&a),则是取变量的地址。

9.7 内 置 函 数 调用函数时需要一定的时间,如果有的函数需要频繁使用,则所用时间会很长,从而降低程序的执行效率。C++提供一种提高效率的方法,即在编译时将所调用函数的代码嵌入到主调函数中。这种嵌入到主调函数中的函数称为内置函数(inline function),又称内嵌函数。在有些书中把它译成“内联函数”。 指定内置函数的方法很简单,只需在函数首行的左端加一个关键字inline即可。

例9.9 将函数指定为内置函数。 #include <iostream.h> inline int max(int a, int b, int c) //这是一个内置函数,求3个整数中的最大者 { if (b>a) a=b; if (c>a) a=c; return a; } void main( ) {int i=7, j=10, k=25, m ; m=max(i, j, k); cout<<"max="<<m<<endl;

由于在定义函数时指定它为内置函数,因此编译系统在遇到函数调用max(i,j,k)时,就用max函数体的代码代替max(i,j,k),同时将实参代替形参。这样,m=max(i,j,k)就被置换成 if(j>i) i=j; if(k>i) i=k; m=i; 内置函数与宏替换有些相似,但不完全相同。宏替换是在编译前由预处理程序进行预处理,它只作简单的字符替换而不作语法检查。而内置函数是在编译时处理的,编译程序能识别内置函数,对它进行语法检查。有些问题既可以用宏来处理,也可以用内置函数处理,显然,内置函数优于宏替换,它不会出现宏替换中可能产生的副作用。

使用内置函数可以节省运行时间,但却增加了目标程序的长度。假设要调用10次max函数,则在编译时先后10次将max的代码复制并插入main函数,大大增加了main函数的长度。因此只用于规模很小而使用频繁的函数,可大大提高运行速度。

9.8 作用域运算符 每一个变量都有其有效的作用域,只能在变量的作用域内使用该变量,不能直接使用其他作用域中的变量。例如: 9.8 作用域运算符 每一个变量都有其有效的作用域,只能在变量的作用域内使用该变量,不能直接使用其他作用域中的变量。例如: #include <iostream.h> float a=13.5; void main( ) {int a=5; cout<<a; }

程序中有两个a变量:一个是全局变量a,实型;另一个是main函数中的整型变量a,它是在main函数中有效的局部变量。根据规定,在main函数中局部变量将屏蔽全局变量。因此用cout输出的将是局部变量a的值5,而不是实型变量的值13.5。如果想输出全局实型变量的值,有什么办法呢?C++提供作用域运算符∷ ,它能指定所需要的作用域。可以把main函数改为: void main( ) {int a=5; cout<<a<<endl; cout<<∷a<<endl; }

运行时输出: 5(局部变量a的值) 13.5 (全局变量a的值) ∷a表示全局作用域中的变量a。请注意:不能用∷ 访问函数中的局部变量。

9.9 动态分配/撤销内存的运算符new和delete 在软件开发中,常常需要动态地分配和撤销内存空间。在第11章中已知C语言中是利用库函数malloc和free分配和撤销内存空间的。但是使用malloc函数时必须指定需要开辟的内存空间的大小。其调用形式为malloc(size) 。size是字节数,需要人们事先求出或用sizeof运算符由系统求出。此外,malloc函数只能从用户处知道应开辟空间的大小而不知道数据的类型,因此无法使其返回的指针指向具体的数据。其返回值一律为void *类型,必须在程序中进行强制类型转换,才能使其返回的指针指向具体的数据。 C++提供了较简便而功能较强的运算符new和delete来取代malloc和free函数(为了与C语言兼容,仍保留这两个函数)。例如:

new int; (开辟一个存放整数的空间,返回一个指向整型数据的指针) new char[10]; (开辟一个存放字符数组的空间,该数组有10个元素,返回一个指向字符数据的指针) new int[5][4]; (开辟一个存放二维整型数组的空间,该数组大小为5*4) float *p=new float(3.14159) (开辟一个存放实数的空间,并指定该实数的初值为3.14159,将返回的指向实型数据的指针赋给指针变量p) new运算符使用的一般格式为 new 类型 [初值]

用new分配数组空间时不能指定初值。 delete运算符使用的一般格式为 delete [ ] 指针变量 例如要撤销上面用new开辟的存放实数的空间(上面第5个例子),应该用 delete p; 前面用new char[10] 开辟的空间,如果把返回的指针赋给了指针变量pt,则应该用以下形式的delete运算符撤销: delete [ ] pt; (在指针变量前面加一对方括号,表示对数组空间的操作)

例9.10 开辟空间以存放一个结构体变量。 #include <string.h> struct Student {char name[10]; int num; char sex; }; void main ( ) { Student *p; p=new Student; strcpy(p->name,"Wang Fun" ); p->num=10123; p->sex=′M′; delete p; }

先声明了一个结构体类型Student,定义一个指向它的指针变量p,用new开辟一段空间以存放一个Student类型的变量,空间的大小由系统根据Student自动算出,不必用户指定。执行new返回一个指向Student类型数据的指针,存放在p中。然后对各成员赋值(通过指针变量p访问结构体变量),最后用delete撤销该空间。 如果由于内存不足等原因而无法正常分配空间,则new会返回一个空指针NULL,用户可以根据该指针的值判断分配空间是否成功。 注意:new和delete是运算符,不是函数,因此执行效率高。malloc要和free函数配合使用,new和delete配合使用。不要混合使用(例如用malloc函数分配空间,用delete撤销) 。

9.10 小结 在本章中介绍了在面向过程的机制基础上,C++对C功能的扩展。它包括: (1) 允许使用以// 开头的注释。 9.10 小结 在本章中介绍了在面向过程的机制基础上,C++对C功能的扩展。它包括: (1) 允许使用以// 开头的注释。 (2) 对变量的定义出现在程序中的任何位置(但必须在引用该变量之前)。 (3) 提供了标准输入输出流cin和cout,它们不用指定输入输出格式符(如%d),使输入输出更加方便。 (4) 可以利用函数重载实现用同一函数名代表功能类似的函数,以方便使用,提高可读性。 (5) 可以使用带缺省值的参数的函数,使函数的调用更加灵活。

(6) 提供变量的引用类型,即为变量提供一个别名,将“引用”作为函数形参,可以实现通过函数的调用来改变实参变量的值。 (7) 增加了内置函数(内嵌函数),以提高程序的执行效率。 (8) 增加了单目的作用域运算符,这样在局部变量作用域内也能引用全局变量。 (9) 用new和delete运算符代替malloc和free函数,使分配动态空间更加方便。 C++对C的扩展还有其他一些。这些扩充使得人们使用结构化程序设计方法进行程序设计时,比以前更加方便和得心应手。有些人在编写小程序时,利用C++编写面向过程的程序,也取得很好的效果。