1、C+程序设计第第2 2章章 C+C+基础知识基础知识第第2章章 C+基础知识基础知识本章学习要点本章学习要点从C语言到C+的发展历程简单的C+程序C+对C的扩充C+的输入输出、数据类型、函数及指针C+的常变量、引用、名字空间、字符串变量C+程序的编写和实现第第2章章 C+基础知识基础知识本章学习目标本章学习目标了解从C语言到C+的发展历程对简单的C+程序有整体的感性认识掌握C+对C的扩充掌握C+的输入输出、数据类型、函数及指针掌握C+的常变量、引用、名字空间、字符串变量熟悉C+程序的编写和实现流程2.1 从C语言到C+C+3.0C+2.0C+1.0带类的带类的CCC+4.0ANSI C+89年
2、,增加类的多继承91年,增加模板增加异常处理、名字空间、运行时类型识别97年,美国C+标准正式发布v下面看几个简单的下面看几个简单的C+程序程序【例2-1】在屏幕上输出一行字符“Hello C+!”。#include /包含头文件命令using namespace std;/使用名字空间stdint main()coutHello C+!endl;/输出字符串到屏幕 return 0;/main函数返回0至操作系统2.2 简单简单C+程序程序标准C+程序和C程序的不同:main函数的返回值为整型 注释符:/使用cout输出 包含头文件iostream名字空间注意【例2-2】通过函数求两个整数a
3、和b的和。#include /包含头文件命令using namespace std;/使用名字空间stdint sum(int x,int y)return x+y;/求和函数int main()int a,b;/定义两个变量a和b coutInput to a and b:ab;/等待用户从键盘输入数据 couta+b=sum(a,b)endl;return 0;2.2 简单简单C+程序程序C+的函数和C语言的函数非常相似 函数的使用仍然需要先声明后使用。如果函数定义在函数调用之后,则必须在前面声明函数原型注意#include /包含头文件命令using namespace std;/使用名
4、字空间stdint main()int a,b;/定义两个变量a和b coutInput to a and b:ab;/等待用户从键盘输入数据 int sum(int x,int y);/sum函数原型声明 couta+b=sum(a,b)endl;return 0;int sum(int x,int y)return x+y;/求和函数2.2 简单简单C+程序程序变量可以在程序的变量可以在程序的任何地方定义,但任何地方定义,但要在使用前要在使用前2.2 简单简单C+程序程序【例例2-3】声明一个关于人的类声明一个关于人的类PersonPerson,人的信息包括,人的信息包括姓名、性别、年龄,
5、程序运行后,我们可以输入自己姓名、性别、年龄,程序运行后,我们可以输入自己的信息,也可以显示自己的信息。的信息,也可以显示自己的信息。#include /包含头文件命令 using namespace std;/使用名字空间std class Person int main();return 0;2.2 简单简单C+程序程序class Person /类的声明public:/以下为类的公用成员函数void SetInfo()/公用成员函数SetInfo coutnamesexage;void Show()/公用成员函数Show cout name:name;cout sex:sex;cout
6、age:ageendl;private:/以下为类的私有数据成员char name20;/私有数据成员namechar sex2;/私有数据成员sexint age;/私有数据成员age;/类声明结束,此处必须有分号 2.2 简单简单C+程序程序int main()/main函数 /定义Person类的两个对象person1,person2Person person1,person2;person1.SetInfo();/对象person1信息输入person2.SetInfo();/对象person2信息输入person1.Show();/对象person1信息输出person2.Show(
7、);/对象person2信息输出return 0;注意:注意:类的声明和对象的定义的语法形式。类中的成员分为数据成员和成员函数,成员的可见性分为 3种:公用、私有、受保护。类的概念的理解:类是一种用户自定义数据类型,它是不占用实际存储空间的。对象的理解:对象是类类型的变量,系统会为对象分配内存空间。2.2 简单简单C+程序程序2.3 C+对对C的扩充的扩充v在输入输出方面的扩充在输入输出方面的扩充v对数据类型的扩充对数据类型的扩充v常变量常变量v在指针方面的扩充在指针方面的扩充v引用的概念引用的概念v在函数方面的扩充在函数方面的扩充v名字空间的概念名字空间的概念v字符串变量字符串变量本章重本章
8、重点点2.3.1 C+的输入输出的输入输出vC语言输入输出的实现语言输入输出的实现 通过输入输出库函数实现通过输入输出库函数实现 C语言的输入输出存在着格式复杂、无法保证安语言的输入输出存在着格式复杂、无法保证安全性、无法对自定义类型整体输入输出等缺点全性、无法对自定义类型整体输入输出等缺点v C+对对C输入输出的扩充输入输出的扩充 C+的输入的输入/输出(输出(I/O)流类库)流类库“流流”的思想的思想 cout、cin对象对象,运算符运算符2.3.2 数据类型的扩展数据类型的扩展空类型引用类型指针类型类类型共用体类型结构体类型数组类型枚举类型构造类型布尔型长双精度型双精度型单精度型浮点型字
9、符型长整型整型短整型整型基本类型数据类型2.3.3 用用const定义常变量定义常变量v直接常量和符号常量直接常量和符号常量v使用符号常量需要注意的问题:使用符号常量需要注意的问题:运行时不分配内存单元运行时不分配内存单元 符号常量没有类型,在编译时不进行类型符号常量没有类型,在编译时不进行类型检查检查 注意替换后的表达式和预想的表达式是否注意替换后的表达式和预想的表达式是否一致一致 int x=1,y=2;#define PI 3.14159#define R x+y coutPI*R*Rendl;输出语句输出的并不是输出语句输出的并不是 3.14159*(x+y)*(x+y),而是而是 3
10、.14159*x+y*x+y。2.3.3 用用const定义常变量定义常变量v为了使常量也能像变量那样进行类型检为了使常量也能像变量那样进行类型检查,查,C+提供了用提供了用const定义常变量的方定义常变量的方法法v定义常变量的语法:定义常变量的语法:const float PI=3.14159;注意:注意:常变量要在定义的同时进行初始化,常变量要在定义的同时进行初始化,可以是具体的数值,也可以是表达式。可以是具体的数值,也可以是表达式。【例2-4】利用常变量计算圆的面积。#include using namespace std;int main()const float PI=3.14;/
11、定义常变量 float radius=0;coutradius;coutThe area of circle is:PI*radius*radiusendl;return 0;2.2 简单简单C+程序程序注意const的位置,一般见到的const的位置可能在类型的前面,但是const也可以在变量名前面,并且两者的含义完全相同。注意 float const PI=3.14;/定义常变量2.3.4 指针指针v指针指针 指针是一个重要概念,如果使用得当可以指针是一个重要概念,如果使用得当可以使程序高效、简洁、紧凑。如果对指针掌使程序高效、简洁、紧凑。如果对指针掌握不牢固,编程则会出现意想不到的错误握
12、不牢固,编程则会出现意想不到的错误 指针是内存单元的地址指针是内存单元的地址 经常所讲的指针是指针变量的简称,是用经常所讲的指针是指针变量的简称,是用来存放指针(地址)的变量。来存放指针(地址)的变量。v本节重点讨论本节重点讨论C+中使用指针需要中使用指针需要注意的地方注意的地方 2.3.4.1 指针与0v空指针空指针 空指针表示空指针表示“未分配未分配”或者或者“尚未指向尚未指向任何地方任何地方”的指针的指针 空指针一般用来判断内存分配是否成功空指针一般用来判断内存分配是否成功 注意:注意:“空指针空指针”与与“野指针野指针”的区别的区别 在指针上下文中的常数在指针上下文中的常数0被编译成空
13、指针被编译成空指针 程序员更常使用符号常量程序员更常使用符号常量NULL来表示空来表示空指针指针 未初始化的指针未初始化的指针【例2-5】指针与0。#include using namespace std;int main()int*p=0;/定义空指针pint*q;/定义野指针qint x=100;/定义整型变量x并初始化为100/*p=50;/若执行则编译出错,不能使用空指针*q=50;/编译通过,但不知把50写到何处p=q=&x;/使指针p和q都指向变量xif(p!=0)/判断指针p是否为空指针cout*p *qendl;/输出变量x的值 return 0;2.2 简单简单C+程序程序i
14、nt *p=NULL2.3.4.2 指针与指针与constint *p=NULLconst int *p=NULLint const *p=NULL指向指向const变量的指针变量的指针int*const p=NULLconst指针指针2.3.4.2 指针与指针与const【例2-6】指向const变量的指针。include using namespace std;int main()const int*p=NULL;/定义指向const变量的指针pconst int a=10;/定义常变量ap=&a;/指针p指向acout*p=*pendl;/输出p所指向单元的内容int b=100;/定义
15、普通变量bp=&b;/指针p指向bcout*p=*pendl;/输出p所指向单元的内容/*p=200;/错误,不能通过p修改p所指向单元内容b=200;cout*p=*pendl;/输出p所指向单元的内容return 0;通过本例可以看到可以改变通过本例可以看到可以改变指向指向const变量的指针的指变量的指针的指向,但是不能通过指针修改向,但是不能通过指针修改指针指向单元内容。指针指向单元内容。2.3.4.2 指针与const【例2-7】const指针。#include using namespace std;int main()int a=10;/定义普通变量aint b=100;/定义普
16、通变量bint*const p=&a;/定义const指针p并初始化指向acout*p=*pendl;/输出p所指向单元内容/p=&b;/错误,不能改变const指针p的指向*p=100;/通过指针修改p所指向单元内容cout*p=*pendl;/输出p所指向单元内容return 0;通过本例可以看到可以改通过本例可以看到可以改变变const指针指向单元的指针指向单元的内容,但是不能改变内容,但是不能改变const指针的指向。指针的指向。2.3.4.2 指针与指针与const【例2-8】指向const变量的const指针。#include using namespace std;int mai
17、n()int a=10;int b=100;/定义指向const变量的const指针p const int*const p=&a;cout*p=*pendl;/输出p所指向单元内容/p=&b;/错误,不能改变指针p的指向/*p=100;/错误,不能改变p所指向单元的内容return 0;对于指向对于指向const变量变量的的const指针,既不指针,既不能改变指针指向单能改变指针指向单元的内容,也不能元的内容,也不能改变指针的指向。改变指针的指向。2.3.4.2 指针与指针与constv小结小结指针和指针和const的关系比较复杂,的关系比较复杂,const有两个有两个位置,可形成三种指针:位
18、置,可形成三种指针:const int *p=NULLint const *p=NULL指向指向const变量的指针变量的指针int*const p=NULLconst指针指针2.3.4.2 指针与指针与constv小结小结指针和指针和const的关系比较复杂,的关系比较复杂,const有两个有两个位置,可形成三种指针:位置,可形成三种指针:const int *const p=NULLint const *const p=NULL指向指向const变量的变量的const指针:指针:2.3.4.3 void指针指针vvoid在作为函数类型和参数类型时为空在作为函数类型和参数类型时为空类型,表示
19、没有返回值或参数。类型,表示没有返回值或参数。vvoid修饰指针时称为修饰指针时称为“无类型指针无类型指针”,表示该指针可以指向任意类型的变量。表示该指针可以指向任意类型的变量。v虽然虽然void指针可以指向任意类型的数据,指针可以指向任意类型的数据,但是在使用但是在使用void指针时必须对其进行强指针时必须对其进行强制类型转换,转换成它所指向单元的实制类型转换,转换成它所指向单元的实际类型,然后才可以使用。际类型,然后才可以使用。2.3.4.3 void指针指针【例2-9】void指针的声明与使用。#include using namespace std;int main()int x=10
20、0;void*p=&x;/定义void指针p指向x int*q=NULL;/定义整型指针q /cout*p=*pendl;/错误 cout*p=*(int*)pendl;/正确 /q=p;/错误 q=(int*)p;/正确 cout*q=*qendl;/输出指针q指向单元内容 return 0;2.3.4.3 void指针指针v为什么要使用为什么要使用void指针指针 因为因为void指针可以指向任意类型的数据,指针可以指向任意类型的数据,所以使用所以使用void指针时把指针时把void指针所指向指针所指向的数据给抽象化了,这样可以增加程序的数据给抽象化了,这样可以增加程序的通用性的通用性 v
21、使用使用void指针的两个例子指针的两个例子void*memcpy(void*dest,const void*src,size_t len);void*malloc(unsigned int size);2.3.4.4 new和和deletevC语言的动态内存管理语言的动态内存管理 malloc()和和free()函数函数 主要缺点主要缺点函数的返回值是函数的返回值是voidvoid*类型类型 分配内存单元时根据参数分配内存单元时根据参数sizesize的值来分配,的值来分配,无法检查错误无法检查错误分配到的内存单元无法初始化分配到的内存单元无法初始化vC+中使用中使用new和和delete运
22、算符进行运算符进行动态内存管理动态内存管理P31 最后最后【例例2-11】使用使用new和和delete动态管理内存单元。动态管理内存单元。#include using namespace std;int main()int*p=NULL;p=new int;cout*p=*pendl;delete p;return 0;2.3.4.4 new和和deletev申请内存空间并进行初始化申请内存空间并进行初始化 指针变量指针变量=new 数据类型数据类型(初值初值);v分配多个连续变量的存储空间分配多个连续变量的存储空间 使用使用new 和和delete 指针变量指针变量 =new=new 数据
23、类型数据类型 元素个数元素个数;delete delete 指针变量指针变量;:兼容兼容C语言的语言的malloc/free方式方式,单个变量的单个变量的new/delete方式方式,多多个变量的个变量的new/delete 方式方式 2.3.4.4 new和和delete2.3.5 引用引用v引用引用就是某一变量的就是某一变量的别名别名,对引用的,对引用的操作与对变量直接操作完全一样操作与对变量直接操作完全一样 v引用的声明方法引用的声明方法 类型标识符类型标识符&引用名引用名=目标变量名目标变量名;2.3.5 引用引用vint a;vint&b=a;20地址地址2000变量变量a引用引用b
24、v在声明一个引用时,引用前面的类型标示在声明一个引用时,引用前面的类型标示符是指目标变量的类型,且必须同时使之符是指目标变量的类型,且必须同时使之初始化,即声明它代表哪一个变量初始化,即声明它代表哪一个变量.【例2-12】使用引用访问变量。#include using namespace std;int main()int x=100;/定义整型变量x int&rx=x;/定义变量x的引用rx coutrx=rxendl;/输出引用rx的内容 rx=200;/给引用rx赋值 coutx=xendl;/输出变量x的内容 return 0;程序运行结果如下:程序运行结果如下:rx=100 x=20
25、02.3.5 引用引用补充:关于引用的简单说明补充:关于引用的简单说明v(1)引用并不是一种独立的数据类型,)引用并不是一种独立的数据类型,声明引用时必须指定其代表某一类型的实声明引用时必须指定其代表某一类型的实体(如变量、类对象),即对它初始化。体(如变量、类对象),即对它初始化。vint a;vint&b=a;vint&b;vfloat a;int&b=a;v(2)引用与其所代表的变量共享同一内)引用与其所代表的变量共享同一内存单元,系统并不为引用另外分配存储空存单元,系统并不为引用另外分配存储空间。间。vint a=3;vint&b=a;vCout&a“&bendl;补充:关于引用的简单
26、说明补充:关于引用的简单说明vint a=3;vint&b=a;/声明b是整型变量的别名vint&c=b;/声明c是整型引用b的别名v(3)对引用的初始化,可以用一个变量)对引用的初始化,可以用一个变量名,也可以用另一个引用。如:名,也可以用另一个引用。如:补充:关于引用的简单说明补充:关于引用的简单说明v(4)引用在初始化后不能再被重新声明)引用在初始化后不能再被重新声明为另一变量的别名。为另一变量的别名。vint a=3,b=4;vint&c=a;vint&c=b;/企图重新声明c为整型变量b的别名补充:关于引用的简单说明补充:关于引用的简单说明v(5)当当&a的前面有类型符时(如的前面有
27、类型符时(如 int&a),它必然是对引用的声明;如果前面没有类型符它必然是对引用的声明;如果前面没有类型符时(时(p=&a),此时的,此时的&是取地址运算符。是取地址运算符。vint a=3,b=4;vint&c=a;vint*p=&b;补充:关于引用的简单说明补充:关于引用的简单说明v实际上,在实际上,在C+程序中很少使用独立变量的程序中很少使用独立变量的引用,如果要使用某一个变量,就直接使用引用,如果要使用某一个变量,就直接使用它的原名,没有必要故意使用它的别名。前它的原名,没有必要故意使用它的别名。前面举的例子只是为了说明引用的特征和基本面举的例子只是为了说明引用的特征和基本的用法。的
28、用法。vC+之所以增加之所以增加“引用引用”,主要是利用它作,主要是利用它作为函数参数,以扩充函数传递数据的功能为函数参数,以扩充函数传递数据的功能补充:关于引用的简单说明补充:关于引用的简单说明在在C语言中,函数的参数传递有以下两种情况:语言中,函数的参数传递有以下两种情况:v(1)值传递:)值传递:将变量名作为形参和实参。将变量名作为形参和实参。此时传递给形参的是实参变量的值,此时传递给形参的是实参变量的值,数据传递是单向的,在函数执行期间数据传递是单向的,在函数执行期间形参值发生变化并不回传给实参。形参值发生变化并不回传给实参。v(2)地址传递:)地址传递:v(2)地址传递:)地址传递:
29、形参是指针变量,实参是变量的地址。形参是指针变量,实参是变量的地址。函数调用时,形参指向实参变量单元,函数调用时,形参指向实参变量单元,数据传递是双向的。数据传递是双向的。v【例例2-13】编写一个函数,交换两个整型变量编写一个函数,交换两个整型变量的值。的值。v(1)值传递:)值传递:教材教材3510 x20y1020 xy2010v(2)地址传递:传递变量的地址(指针)地址传递:传递变量的地址(指针)v【例例2-13】编写一个函数,交换两个整型变量编写一个函数,交换两个整型变量的值。的值。10 x20y*x*y2010v(3)引用传递:)引用传递:v【例例2-13】编写一个函数,交换两个整
30、型变量编写一个函数,交换两个整型变量的值。的值。#include using namespace std;void swap(int&x,int&y)int tmp;tmp=x;x=y;y=tmp;int main()int x=10,y=20;cout交换前:x=x,y=yendl;swap(x,y);cout交换后:x=x,y=yendl;return 0;2.3.5 引用引用 别名别名x10变量变量x20变量变量y 别名别名y1020对引用的进一步说明对引用的进一步说明v(1)不能建立数组的引用。)不能建立数组的引用。“引用引用”只能是变量或对象的引用。数组是只能是变量或对象的引用。数组
31、是具有某种类型的数据的集合,其名字表示该具有某种类型的数据的集合,其名字表示该数组的起始地址而不是一个变量。所以不能数组的起始地址而不是一个变量。所以不能建立数组的引用。建立数组的引用。char c6=“hello”;char&rc=c;v(3)可以将变量的引用的地址赋给一个指针,)可以将变量的引用的地址赋给一个指针,此时指针指向的是原来的变量,如此时指针指向的是原来的变量,如 int a=3;int&b=a;int*p=&b;v 由于引用不是一种独立的数据类型,不能建由于引用不是一种独立的数据类型,不能建立指向引用类型的指针变量:立指向引用类型的指针变量:int&*p=&a;对引用的进一步说
32、明对引用的进一步说明v(4)可以建立指针变量的引用,如)可以建立指针变量的引用,如 int i=3;int*p=&i;int*&pt=p;对引用的进一步说明对引用的进一步说明v(5)可以用)可以用const对引用加以限定,不允许对引用加以限定,不允许改变该引用的值。如改变该引用的值。如 int i=5;const int&a=i;a=3;v但可以但可以 i=3 对引用的进一步说明对引用的进一步说明 利用常引用作为函数形参,既能提高程序的执行利用常引用作为函数形参,既能提高程序的执行效率,又能保护传递给函数的数据不在函数中被效率,又能保护传递给函数的数据不在函数中被改变,达到保护实参的目的改变,
33、达到保护实参的目的 对引用的进一步说明对引用的进一步说明 void show(const int&x)x=8;cout“x=“xendl;v(6)可以用常量或表达式对引用进行初始化,)可以用常量或表达式对引用进行初始化,但此时必须用但此时必须用const作声明。如作声明。如 int a=3;const int&b=a+3;v int temp=a+3;const int&b=temp;v 用这种方式不仅可以用表达式对引用进行初始用这种方式不仅可以用表达式对引用进行初始化,还可以用不同类型的变量对之初始化。化,还可以用不同类型的变量对之初始化。对引用的进一步说明对引用的进一步说明v double
34、 d=3.14159;v const int&a=d;int temp=d;const int&a=d;对引用的进一步说明对引用的进一步说明v引用作为函数的返回值引用作为函数的返回值【例2-14】引用作为函数的返回值。class stringpublic:/重载赋值运算符string&operator=(const string&right);string&operator+=(const string&right);int compare(const string&)const;/字符串比较private:unsigned buflen;char*buffer;2.3.5 引用引用v面向过程
35、的面向过程的C+程序中的函数与程序中的函数与C语言语言中的函数基本相同中的函数基本相同v面向对象的面向对象的C+程序中的函数有成员程序中的函数有成员函数和公共函数之分函数和公共函数之分v主要讨论面向过程的主要讨论面向过程的C+程序中函数程序中函数与与C语言函数的区别语言函数的区别2.3.6 函数函数2.3.6.1 函数原型声明函数原型声明v在函数尚未定义的情况下,先将函数的形在函数尚未定义的情况下,先将函数的形式告诉编译系统,以便编译能够正常进行式告诉编译系统,以便编译能够正常进行 v函数原型声明的语法形式有两种:函数原型声明的语法形式有两种:(1)返回值类型)返回值类型 函数名函数名(参数类
36、型参数类型1,参数类型参数类型2,.);(2)返回值类型)返回值类型 函数名函数名(参数类型参数类型1 参数名参数名1,参数类型参数类型2 参数名参数名2,.);函数原型声明和函数定义是不同的。函数原型声明不是一个独立的完整的函数单位,它仅仅是一条语句,因此在函数原型声明后面一定要加上分号。2.3.6.2 函数默认参数函数默认参数v在多次调用一个函数将实参传递给形参时,其在多次调用一个函数将实参传递给形参时,其中可能有一个或几个参数,它们传递进来的实中可能有一个或几个参数,它们传递进来的实参值多次相同参值多次相同v在定义或声明函数时,给形参一个默认值,如在定义或声明函数时,给形参一个默认值,如
37、果在调用时没有给该形参传递实参值,则使用果在调用时没有给该形参传递实参值,则使用默认值作为该形参的值;如果调用时给该形参默认值作为该形参的值;如果调用时给该形参传递了实参值,则使用实参的值作为该形参的传递了实参值,则使用实参的值作为该形参的值。值。2.3.6.2 函数默认参数函数默认参数【例例2-16】求两个或三个正整数中的最大值,使用带有求两个或三个正整数中的最大值,使用带有默认参数的函数实现。默认参数的函数实现。#include using namespace std;int main()int max(int,int,int=0);/带有默认参数的函数原型声明int a=5,b=8,c=
38、10;coutmax of a and b is:max(a,b)endl;coutmax of a,b and c is:max(a,b,c)endl;return 0;/定义带有默认参数的函数int max(int a,int b,int c=0)if(a b)a=b;if(a c)a=c;return a;2.3.6.2 函数默认参数函数默认参数1.1.指定默认值参数默认值的位置:为了避免混淆,最指定默认值参数默认值的位置:为了避免混淆,最好只在函数原型声明时指定默认值。好只在函数原型声明时指定默认值。2.2.当只有部分形参带有默认值时,带有默认值的参数当只有部分形参带有默认值时,带有默
39、认值的参数必须放在形参表的右端。必须放在形参表的右端。3.3.当一个函数既是重载函数,又是带有默认参数的函当一个函数既是重载函数,又是带有默认参数的函数时,要注意不要出现二义性的问题数时,要注意不要出现二义性的问题调用带有默认参数的函数时,实参的个数可以与形调用带有默认参数的函数时,实参的个数可以与形参的个数不同,对于实参未给出的,可以从形参的参的个数不同,对于实参未给出的,可以从形参的默认值中获得,利用这一特性,可以使函数的使用默认值中获得,利用这一特性,可以使函数的使用更加灵活。更加灵活。2.3.6.3 函数与引用函数与引用v函数与引用联合使用主要有两种方式:函数与引用联合使用主要有两种方
40、式:v1.函数的参数是引用函数的参数是引用 当使用引用作为函数的形参时,引用不是一个当使用引用作为函数的形参时,引用不是一个单独的变量,不需要在内存中分配存储单元,单独的变量,不需要在内存中分配存储单元,实参向形参传递的是变量的名字。使用引用作实参向形参传递的是变量的名字。使用引用作为函数的形参可以部分代替指针,降低了程序为函数的形参可以部分代替指针,降低了程序的复杂度,提高了程序的执行效率,同时也提的复杂度,提高了程序的执行效率,同时也提高了程序的可读性。高了程序的可读性。v2.函数的返回值是引用函数的返回值是引用 2.3.6.3 函数与引用函数与引用v函数与引用联合使用主要有两种方式:函数
41、与引用联合使用主要有两种方式:v2.函数的返回值是引用函数的返回值是引用v以引用作为函数的返回值是为了使函数可以作为以引用作为函数的返回值是为了使函数可以作为左值而被赋值。函数的返回值为引用类型表示该左值而被赋值。函数的返回值为引用类型表示该函数的返回值是一个内存变量的别名。可以将函函数的返回值是一个内存变量的别名。可以将函数调用作为一个变量来使用,可以为其赋值。数调用作为一个变量来使用,可以为其赋值。v引用作为函数的返回值引用作为函数的返回值【例2-14】引用作为函数的返回值。class stringpublic:/重载赋值运算符string&operator=(const string&r
42、ight);string&operator+=(const string&right);int compare(const string&)const;/字符串比较private:unsigned buflen;char*buffer;2.3.5 引用引用2.3.6.3 函数与引用函数与引用v函数与引用联合使用主要有两种方式:函数与引用联合使用主要有两种方式:v2.函数的返回值是引用函数的返回值是引用v定义返回引用的函数时,注意不要返回对定义返回引用的函数时,注意不要返回对该函数内的自动变量的引用。否则,因为该函数内的自动变量的引用。否则,因为自动变量的生存期仅局限于函数内部,当自动变量的生存
43、期仅局限于函数内部,当函数返回时,自动变量就消失了,函数就函数返回时,自动变量就消失了,函数就会返回一个无效的引用。函数返回的引用会返回一个无效的引用。函数返回的引用是对某一个函数参数的引用,而且这个参是对某一个函数参数的引用,而且这个参数本身也是引用类型数本身也是引用类型2.3.6.4 函数与函数与constvconst修饰函数的参数修饰函数的参数vconst修饰函数的返回值修饰函数的返回值vconst修饰整个函数修饰整个函数2.3.6.4 函数与函数与constvconst修饰函数的参数修饰函数的参数 调用函数时用相应的值初始化调用函数时用相应的值初始化const常量常量 函数体按照函数体
44、按照const所修饰的部分进行常量化所修饰的部分进行常量化 void show(const int&x)x=8;cout“x=“xendl;2.3.6.4 函数与函数与constvconst修饰函数的返回值修饰函数的返回值 用于二目操作符重载函数并产生新对象用于二目操作符重载函数并产生新对象const Fraction operator*(const Fraction&left,const Fraction&right)return Fraction(left.numerator()*right.numerator(),left.denominator()*right.denominator(
45、);返回值用const修饰可以防止允许这样的操作发生:Fraction a,b;Fraction c;(a*b)=c;2.3.6.4 函数与函数与constvconst修饰整个函数修饰整个函数 这种情况发生在类的成员函数时这种情况发生在类的成员函数时 const的位置放在函数参数表的后面的位置放在函数参数表的后面 class stringpublic:int compare(const string&)const;/字符串比较private:unsigned buflen;char*buffer;2.3.6.5 函数重载函数重载问题:问题:求求2个数的和。个数的和。(分别考虑整数、浮点数的情况
46、分别考虑整数、浮点数的情况)int add_i(int a,int b)coutCall integer add function.endl;return a+b;float add_f(float a,float b)coutCall float add function.endl;return a+b;2.3.6.5 函数重载函数重载C+允许允许在同一个作用域中在同一个作用域中用同一函数名定义用同一函数名定义多个函数,多个函数,这些函数的参数个数或参数类型这些函数的参数个数或参数类型不相同,这些同名的函数用来实现同一类的不相同,这些同名的函数用来实现同一类的操作。这就是操作。这就是函数的重
47、载函数的重载。即对一个函数名。即对一个函数名重新赋予它新的操作,使一个函数名可以多重新赋予它新的操作,使一个函数名可以多用。用。2.3.6.5 函数重载函数重载【例2-18】使用add为函数名定义整数的加法和两个浮点数的加法.int add(int a,int b)/整数加法的add函数定义 coutCall integer add function.endl;return a+b;float add(float a,float b)/浮点数加法的add函数定义 coutCall float add function.endl;return a+b;2.3.6.5 函数重载函数重载【例2-19
48、】使用add作为函数名定义两个整数的加法函数和三个整数的加法函数。int add(int a,int b)return a+b;float add(float a,float b,int c)return a+b+c;2.3.6.5 函数重载函数重载函数重载函数重载需要函数参数的类型或个数必须至少需要函数参数的类型或个数必须至少有其中之一不同有其中之一不同,函数返回值类型可以相同也可以函数返回值类型可以相同也可以不同不同。但是,。但是,不允许参数的个数和类型都相同而只不允许参数的个数和类型都相同而只有返回值类型不同有返回值类型不同。从语法上来说,可以让两个或。从语法上来说,可以让两个或多个完全
49、不相干的函数使用相同的函数名,进行重多个完全不相干的函数使用相同的函数名,进行重载,但是这样做使得程序的可读性下降,不建议这载,但是这样做使得程序的可读性下降,不建议这样做。使用同名函数进行重载时,重载函数在功能样做。使用同名函数进行重载时,重载函数在功能上应该相近或属于同一类函数。上应该相近或属于同一类函数。函数调用需要一定的时间和空间的开销。函数调用需要一定的时间和空间的开销。(保护现场(保护现场/恢复现场,参数传递等)恢复现场,参数传递等)main函数函数fun函数函数调用调用fun函数函数结束结束2.3.6.6 内置函数内置函数2.3.6.6 内置函数内置函数v由于调用函数时系统需要一
50、定的时间和空间的由于调用函数时系统需要一定的时间和空间的开销(保护现场开销(保护现场/恢复现场,参数传递等)。恢复现场,参数传递等)。当函数体很小而又需要频繁调用时,运行效率当函数体很小而又需要频繁调用时,运行效率与代码重用的矛盾变得很突出。这时函数的运与代码重用的矛盾变得很突出。这时函数的运行时间相对比较少,而函数调用所需的栈操作行时间相对比较少,而函数调用所需的栈操作等却要花费比较多的时间。等却要花费比较多的时间。2.3.6.6 内置函数内置函数vC+解决这个问题的方法就是解决这个问题的方法就是内置函数内置函数(inline function),也称为),也称为内联函数或内嵌内联函数或内嵌