1、,第二章 从C语言向C+过渡,主讲:宋丽红,面向对象程序设计(C+) Oriented Object Programming (C+),第二章 从C语言向C+过渡,2-1 C+语言的发展过程 2-2 在较小范围内如何将C+增强C 2-3 在较大范围内如何将C+增强C,2-1 C+语言的发展过程,C+语言基于C,是C的一个超集集合。C+继承了C的全部优点,而且还支持面向对象特征。C+由BCPL和Simula67的某些灵感而导致产生的。1980年,C+由贝尔实验室的Bjarne Stroustrup创建,被称为带类的C。1994年,建立ANSI C+标准。,2-2 在较小范围内如何将C+增强C,一
2、、I/O流控制二、内联函数三、函数重载四、默认参数的函数五、new和delete六、const说明符七、引用八、程序结构九、其他,2-2 在较小范围内如何将C+增强C,2.2.1 I/O流控制 C+中输入/输出流(一般叫iostreams或streams)提供了C的stdio.h库中的所有功能。 输入/输出流用作将具有类型的对象转换成可读的正文,反之亦然。流能读写二进制数据。 C+程序以四个预定义的流开始,它们是:cin标准输入、cout标准输出、cerr标准错、clog缓冲的cerr。标准输入输出流 p23 在iostream.h中说明 cout输入流接收变量 couta; coutafc;
3、,2-2 在较小范围内如何将C+增强C,2.2.1 I/O流控制 2、使用控制符 #include 注意 1、输入流能自动跳过空白字符 2、字符串输入避免溢出,可采取以下方法:char arraySIZE; cin.width(sizeof(array); cinarray;,2-2 在较小范围内如何将C+增强C,2.2.2 内联函数 使用关键字inline说明的函数是内联函数。作用相当于带参数的宏。使用内联函数的必要性 内联函数增加了代码空间,但减少了执行时间(函数调用开销) #include void main() char c; int isnumber(char);coutc;if(i
4、snumber(c) cout=0 对于isnumber这样简单的函数,使用函数调用的方法(特别是多次调用)将大大降低运行效率,可以采用if(c=0&c=9)?1:0)表达式替换的方法。但是,手工替换很烦琐,最好让编译程序去做。内联函数是程序行的扩展,主要是解决程序的运行效率。,2-2 在较小范围内如何将C+增强C,内联函数的使用(1) 在函数声明和定义的最前面加关键字inline 在函数声明时必须有inline,定义时可有可无。 #include void main() char c;inline int isnumber(char); inline int isnumber(char c)
5、 /或用int isnumber(char c) return(c=0 ,2-2 在较小范围内如何将C+增强C,内联函数的使用(2)内联函数必须在调用之前声明或定义。因为内联函数的代码必须在被替换之前已经生成被替换的代码。 #include inline int isnumber(char c) return(c=0 ,2-2 在较小范围内如何将C+增强C,内联函数的函数体限制 内联函数中不能含有复杂的结构控制语句,否则,编译时将该函数视同普通函数那样产生函数调用代码。 递归函数是不能被用来做内联函数的。 内联函数只适合于只有15行的小函数,而且不能频繁地被调用。,2-2 在较小范围内如何将C
6、+增强C,2.2.3 函数重载使用重载函数的必要性在不同类型上作相同运算而又用相同名字的情况,称为重载。,int add(int x,int y) int temp; temp=x+y; return temp; double add(double x,double y) double temp; temp=x+y; return temp; main() int a=4,b=5; double x=12.5,y=75.75; coutadd(a,b)”t”add(x,y)endl; ,运行结果为: 9 88.25,2-2 在较小范围内如何将C+增强C,使用重载函数的必要性使用不同数目的参数,
7、#include int mul(int x,int y) int temp; temp=x*y; return temp; int mul(int x,int y,int z) int temp; temp=x*y*z; return temp; main() int a=5,b=10,c=20; coutmul(a,b)”n”mul(a,b,c)endl; ,运行结果为: 50 1000,2-2 在较小范围内如何将C+增强C,匹配重载函数的顺序 只要参数表互不相同,C+就会根据所给参数调用正确的函数。 (1)寻找一个严格的匹配 (2)通过内部转换寻求一个匹配 (3)通过用户定义的转换寻求一
8、个匹配使用说明 (1)重载函数仅仅是返回类型不同是不够的 重载函数至少在参数个数、参数类型或参数顺序上有所不同 (2)不能用typedef定义的类型名来区分重载函数声明中的参数 (3)重载函数应该具有相同的功能 通过名字粉碎来区分重载函数,2-2 在较小范围内如何将C+增强C,2.2.4 默认参数的函数默认参数的目的 调用某函数时传递的参数经常是同一值,则可使用默认参数,即调用函数时不给出实参,而是直接取默认值。默认参数的声明若有函数声明,则在声明中默认参数,不能写在定义中;若无函数声明,则在定义中默认参数。,2-2 在较小范围内如何将C+增强C,默认参数的顺序规定默认参数应从右至左逐渐定义。
9、void fun(int a=1,int b,int c=3); void fun(int a,int b=1,int c=3); 当调用参数时只能向左匹配参数(靠右面的默认参数先有效)。fun(5,10); - a=5,b=10,c=3默认参数与函数重载 默认参数可以将一系列重载函数合成一个为函数,但由于必须从右至左定义,并向左匹配参数,因此它没有重载函数灵活,而且数据类型也有限制。默认值的限定默认值可为全局变量、全局常量和函数,即不能是局部变量。,2-2 在较小范围内如何将C+增强C,2.2.5 new和delete堆内存动态内存(在运行时申请内存)。 用户内存:代码区、全局数据区、栈区、
10、堆new和delete的格式创建、销毁一变量: new 数据类型(初始值); delete 指针名; int *p; p=new int; delete p;创建、销毁一数组: new 数据类型长度; delete指针名; int *p; p=new int30; delete p;,2-2 在较小范围内如何将C+增强C,说 明new类似于函数malloc(),分配堆内存,但比malloc()更简练。new的操作数为数据类型,它可以带初始化值表或单元个数。new返回一个具有操作数的数据类型的指针。new和delete是C+专有的操作符,它们不用头文件声明。 delete类似于free(),释放
11、堆内存。delete的操作数是new返回的指针,当返回的是new分配的数组时,应该带。 deletedata;由于堆对象的生存期是从创建对象到销毁或程序结束,因此,删除不再需要的堆对象是一个必须进行的工作。,2-2 在较小范围内如何将C+增强C,2.2.6 const说明符 在说明中根据不同情况,const的位置略有不同。 const int i=5; i=10;常量定义功能和C中的符号常量定义类似,比符号常量更好的是用const定义的常量具有数据类型。const说明的数据是真正的数据被登记在符号表中,具有名字、类型和值。常量定义时必须初始化,初始化值是常量或常量表达式。 const floa
12、t pi=3.14;常量同样有全局和局部之分。常量可以定义在头文件中。,2-2 在较小范围内如何将C+增强C,指向常量的指针const 数据类型 *指针名; 指针类型前加const,const int *p; p是指针,是指向整型常量的指针,意味着*p不能改变,但是p可以改变。 即 p=#; *p=#;,0067:f600,10,0067:fd66,变量p,常量i,0067:f600,const int i=10,j=20; const int *p=,0067:f700,20,常量j 0067:f700,2-2 在较小范围内如何将C+增强C,指针常量 数据类型 * const 指针名; 指针
13、名前加const, int * const p; p是常量,是指向整型数据的指针常量,意味着p不能改变,但是*p可以改变。 即 p=#; *p=#; 定义指针常量时必须初始化,初始化值是字符串常量的地址。,0067:f600,10,0067:f600,0067:fd66,常量p,变量i,int i=10; int * const p=,20,2-2 在较小范围内如何将C+增强C,指向常量的指针常量const 数据类型 * const 指针名; 指针类型和指针名前均加const const int * const p; p是指针常量,是指向整型常量的指针常量,意味着p不能改变,*p也不能改变。即
14、 p=#; *p=#;,0067:f600,10,0067:f600,0067:fd66,常量p,常量i,const int i=10; const int * const p=,2-2 在较小范围内如何将C+增强C,用const修饰形式参数 void func(const struct student *s)虽然以指针方式传递一个结构体指针,但对源数据不能做修改。用const修饰成员函数 表示该成员函数不可以改变对象属性值。int getAge() const;,2-2 在较小范围内如何将C+增强C,作业: P32 2.6 (3) P99 5.8 P184 8.9,2-2 在较小范围内如何将
15、C+增强C,2.2.7 引用引用的概念 T 初始化目标类型必须与引用的数据类型一致或可以转化成引用的数据类型。 P188不能建立引用数组,也不能引用void型指针。没有引用的引用,也没有引用的指针,2-2 在较小范围内如何将C+增强C,用引用传递函数参数用引用可以实现C中地址传送的功能,而且比地址(指针)传递更简单和易于理解。注意重载函数。 P191引用与指针一样,可以返回多个值。P192,main() int a=5,b=10;void swap(int ,main(),swap(),5,10,5,x:a:,y:b:,a:,b:,2-2 在较小范围内如何将C+增强C,函数返回值是引用函数返回
16、值是引用将不产生返回值的副本,但是,不能返回一个不在作用域范围内的变量或对象的引用。函数返回值是引用可以使函数成为左值。 float test1=4.5 与指针一样,当函数返回引用时,注意避免产生悬挂引用。,2-2 在较小范围内如何将C+增强C,用const限定引用当函数需传递的实参是很大的数据类型时(数组、结构体),参数传递采用指针或引用。但是,采用指针和引用就存在修改实参的风险。因此,用const来限定引用作为函数的形参。不允许对引用进行赋值。 引用总是const的,所以不需要const double const堆中变量的引用用堆空间初始化引用,既可以用指针释放,也可以用引用释放堆空间。,
17、2-2 在较小范围内如何将C+增强C,2.2.8 程序结构程序=(算法+数据结构)算法与数据结构是一个整体 封装和信息隐藏是面向对象的基本要素。算法总是离不开数据结构,算法含有对数据结构的访问,算法只能适用于特定数据结构。程序=(算法)+(数据结构)数据结构与算法分离。 软件系统的规模越来越大,复杂性不断增长,以致不得不对“关键数据结构”重新评价。 数据结构的主要欠缺是应用范围和可见性。许多重要的过程和函数(子程序)的实现严格依赖与关键数据结构,如果这些关键数据结构的一个或几个数据有所改变,则涉及到整个软件系统。,2-2 在较小范围内如何将C+增强C,2.2.9 其他(1)注释行 / 比 /*
18、 */ 更容易,没有必要记住注释结尾在块(分程序)内说明 允许在使用时才说明变量作用域限定运算符 :表示全局变量int i=10;main() int i=5;:i+=10;cout”i=”iendl;i=20,2-2 在较小范围内如何将C+增强C,2.2.9 其他(2)void类型 void *pr; float fpr; pr=fpr; fptr=(float)pr;函数原型无名共用体 直接用名字存取void main() union int i; float f; ;f=3.0;显式类型转换 可以转换为用户定义类型,2-3 在较大范围内如何将C+增强C,一、 类的构造和数据封装二、 私有、保护和公共部分三、 构造函数和析构函数四、 类属性与友元五、 类中运算符和函数名重载六、 导出类七、 虚拟函数八、 流库九、 类模板,