C++备课笔记_钱能

C++备课笔记_钱能

ID:83011067

大小:332.13 KB

页数:124页

时间:2023-07-04

上传者:无敌小子
C++备课笔记_钱能_第1页
C++备课笔记_钱能_第2页
C++备课笔记_钱能_第3页
C++备课笔记_钱能_第4页
C++备课笔记_钱能_第5页
C++备课笔记_钱能_第6页
C++备课笔记_钱能_第7页
C++备课笔记_钱能_第8页
C++备课笔记_钱能_第9页
C++备课笔记_钱能_第10页
资源描述:

《C++备课笔记_钱能》由会员上传分享,免费在线阅读,更多相关内容在行业资料-天天文库

“C++程序设计”笔记(课程名:计算引论)(教材:钱能清华大学出版社)(本笔记中的例题均在VC++6.0环境下通过)刘军荣:liujr@cs.sjtu.edu.cn1C++入门学习目标:1.对C++语言有一个大致的了解2.能够编写简单的C++程序1.1从C到C++1972年:贝尔实验室开发出了C语言,ー经出现就以其独有的特点风靡了全世界:1.(1)语言简洁、紧凑,使用方便、灵活。C语言只有32个关键字,程序书写形式自由。2.(2)丰富的运算符和数据类型。3.(3)可以直接访问内存地址,能进行位操作,使其能够胜任开发操作系统的工作。但C语言在盛行的同时,也暴露出它的局限:1.c类型检査机制相对较弱,使得程序中的一些错误不能在编译时发现;2.C本身几乎没有支持代码重用的语言结构,因此ー个程序员精心设计的程序,很难为其他程序所用;3.当程序れ规模达到一定的程度时,程序员很难控制程序的复杂性。1980年,贝尔实验室的BjarneStroustrup开始对C进行改进和扩充。1983年正式命名为C++。在经历了3次C++修订后,1994年制定了ANSIC++标准的草案。以后又经过不断完善,成为目前的C++。C++仍在不断发展中。美国微软公司现已推出C#(CSharp)语言,来代替C++语言。

1C++:包括了整个C:C的全部特征、属性、优点支持面向对象编程(OOP)包括过程性语言部分和类部分过程性语言部分:与C无本质上的区别类部分:面向对象程序设计的主体1.2程序与语言程序:是任何有目的的、预想好的动作序列,是ー种软件。对机器而言:按硬件设计规范编制的动作序列(即:机器指令序列)对人而言:用语言(髙、低级语言)编写的语句序列;源文件、源程序、源代码程序语言的发展:低级语言ー髙级语言程序设计首要目标:可读性、易维护性、可移植性可读:就是在使用的书写风格和易懂的语句编写程序。易维护:是指当业务需求发生变化时,不需要太多的开销就可以扩展和增强程序的功能。可移植:是指编写的程序在各种计算机和操作系统上都能运行,并且运行结果ー样。1.3结构化程序设计是面向过程的程序设计主要思想:功能分解、逐步求精例:计算ー个公司职员的平均エ资将其拆分为以下子任务:1)找出ー个人的收入2)计算总共有多少职员3)计算工资总额4)用职员人数去除工资总额计算工资总额又可分为ー系列子任务1)找出每个职员的档案2)读出エ资数额3)把エ资加到部分和上4)读出下个职员的档案缺点:可重用性极差1.4面向对象程序设计面向对象是一种思考方法;世界上的任何东西都是一个对象;例如花,树,动物。任何系统都是由对象构成的(当然系统也是ー个对象);例如法律系统,文化系统,教育系统。基本思想:把信息和对这些信息的处理作为ー个整体一对象,类是对象的数据类型C++:是支持面向对象程序设计的语言C++的三大特性:封装性(数据隐藏):目的是增强安全性和简化编程,使用者不必了解具体的实现细节,而只需要通过外部接口,以特定的访问权限,来使用类的成员。classWatchpublic:voidSetTime(intNewH,intNewM,intNewS);voidShowTime();private:intHour,Minute,Second;

2);继承性(软件重用):C++采用继承支持重用的思想,程序可以在扩展现有类型的基础上声明新类型。新子类是从现有类型派生出来的,称为派生类或子类,而原有类称为父类或基类或超类。classStopWatch::Watch(public:voidStart();voidStop();}多态性:通过继承的方法构造类,采用多态性为每个类指定表现行为。学生类大学生类:髙等数学、计算机、普通物理、英语中学生类:语文、数学、物理1.4程序开发过程build:compile+link1.5最简单的程序程序体:程序体由声明语句和函数组成例:〃文件名:abc.cpp/・该程序的功能是:输出:Iamastudent.*/

3#includevoidmainO{coutくく“Iamastudent.

4";}说明:1.大小写区分(即:abc与Abe不同)2.C++系统是函数驱动的,ー个可执行程序必须有、且只能有一个主函数:main(),作为程序的人口3.C++语句以分号(;)结束,一行可以写多条语句,一条语句可以分多行写4.所有的对象(变量)必须先定义,或先声明、后使用5.以双引号括起的为字符串常量,里边的"\"为转义字符例:^includeintx=5,X=10;voidmainO{inty=x*x;coutくく"y=x*x="くくyくく“y=X*X="«X*X«"

5:::::::::::::::::

6”;}/・执行结果:y=x*x=25y=X*X=100:::::::::::::::::*/*注释:/**ノ和//C++程序结构〈编译预处理:#、程序体1.7函数函数的组成:「函数属性[内部函数।外部函数]函数返回类型小明部分《函数名函数形参名、函数形参类型说明函数Y对象定义或声明语句I函数体\「语句〔执行部分イ...【语句函数格式:函数属性标识符函数返回类型标识符函数名(形参说明列表))其中形参说明列表:如果有多个形参,各形参之间用逗号(,)分隔说明:1.ー个函数如果没有返回值,则函数的返回类型标识符用“void”代替,函数体中不必有return

7语句(如果有return语句,仅仅起提前返回的作用);否则用返回值的类型标识符,函数体中必须有return语句。1.函数与函数之间的关系是调用与被调用的关系,main。函数只能是调用函数,不可以被调用。2.函数只有定义或被声明后,オ可以被调用。函数声明:由函数原型加分号组成。例:intmax(int,int);函数原型:返回类型函数名(形参类型,…,形参类型)例:Sincludeintmax(int,int):〃函数声明语句:函数原型加分号voidmain(){intx=109,y=110;cout«max(x,y)«endl;〃函数调用}intmax(intx,inty)〃被调用函数定义{if(x

8变量:存储信息的单元,每个变量对应一段连续的内存空间,基本类型整型:int字符型:char实型(浮点型){单精度型:float双精度型:doubletype[]C++的数据类型/构造类型结构:联合:枚举:structunionenumclass指针类型:type,空类型:void内存空间的最小单位:字节数据类型的作用:编译器预算对象分配的内存空间大小注意:数据无“void”类型,指针有“void”类型不同的计算机,各类型的变量所占内存空间有所不同bool型:在ANSIC++中具有ANSI:美国国家标准协会(AmericanNationalStandardsInstitute)求某个类型的变量所占内存长度:利用运算符sizeof例:^includeくiostream.h>voidmain(){shortintxl;intx2;chary;//longdoublez;cout«sizeof(xl)«**«sizeof(x2)«**〈(sizeof(y)くぐ"«sizeof(float)«""«sizeof(double)«*"«sizeof(longdouble)«endl;レ/执行结果:2414881.1变量定义变量:在程序的运行期间,值会变、或值可变的数据量。变量名:每个变量必须有名,即:变量标识符。1.命名变量名规定:1不能与C++的保留字、库函数名、类名、对象名同名2只能由26个大小写字母、数字和下划线组成3只能以字母或下划线开头way__cool,RightOn,Bits32,Case,iPtr,MyCarcase,52Select,Alot,-Wsin,cout,string命名规则和程序书写风格:p/15〜16

91.变量定义变量定义:每个变量必须被确定类型、变量名。例如:intx,y;注意:一条语句中只能定义同一类型的ー个或多个变量规定:变量必须“先定义、后使用”。程序编译时将分配存储单元,及进行语法检査。唯一性:ー个变量一个名,不同的名表示不同的变量。2.变量赋值与初始化变量初始化:在定义变量的同时进行赋值例:intx=5,y,z=9;变量赋值:利用赋值运算符进行值的更新例:intx=5;//x初始化为5x=100I〃把100赋给xx=x/2+7;〃把x/2+7的计算结果赋给x,即:x=573.给类型起“别名”:typedef例:ttincludetypedefshortintI;voidmainO{Ixl;intx2;chary;cout«sizeof(xl)«*"くくsizeof(x2)くく""«sizeof(y)«""«sizeof(float)«""«sizeof(double)«endl;"/执行结果:24148注意:typedef并不产生新的类型4.4常量常量:常数、或在程序运行过程中值始终不变的数据量。例如:x=5+19.7;其中5和19.7就是常量常量有类型:5一一整型19.7——实型七,一字符型1•整型常量C++提供3种表示整型常量的形式:十进制:123,-123,0;ハ进制:以〇(零)开头的整数常量例如:0123,即:01238=1*82+2*8'+3*8°=64+16+3=8310-0123:表示八进制的负数123,为十进制的ー83。十六进制:以Ox(零和x)开头的整数常量例如:0x123,即:Oxl23I6=l*162+2*16l+3*160=256+32+3=291lo

10-0x123:表示八进制的负数123,为十进制的-291。例:#includeくiostream.h>voidmain(){cout«123«**«0123«*"くく・〇123くぐ"«0xl5«""«-0xl5«""«0xl23«*"«"0xl23«endl;}〃执行结果:12383-8321-21291-291整型常量的类型:整型常量有类型,系统自动识别在整型常量的后面加字母“L”或“1”(小写),表示该常量是长整型的。注意:常量无unsigned型2.实型常量C++提供2种实型常量的表示形式:十进制:由数字和小数点组成。必须带小数点例如:12.123、0.0、.0、〇.、9453.13124指数形式:蛙E(或e)整数。E前必须有数字,E后必须是整数例如:123E3(或:123e3)即:123x10,1.234e5即:1.234x1()5有效位:单精度(float)7位双精度(double)15位实型常量在内存中所占字节数:以double型进行存储,占8字节。但是,在后面加f,则以float型存储,占4字节34.5f//float34.5//double34.5e23L//longdouble34.5e231//longdouble例:itincludevoidmain(){cout«sizeof(1.23)«**くくsizeof(1.23f)くくendl;レ/执行结果:843.字符常量用单引号括起的单个字符特殊字符以“ヽ”开头(P/18)例如:‘1',’〇’,'/','=','a','b','

11','\t','\\'a二'a';a='A';a='\101';8进制的101等于10进制的65,ASCH值为65的字符是:A所以,实际上:a='A';注意:在内存中,字符以ASCII码存储,是以整数表示的所以,字符和整数之间可以互相赋值例:ttinclude

12voidmainO{intxl二'A',x2='0',x3=0;charc=97;cout«xl«"〃くくx2くく“"«x3«""«c«endl;レ/执行结果:65480a4.字符串常量用双引号括起的字符序列例如:"abc.|*88住宅ok”""S空字符串"":只有一个空字符的字符串"a":只有一个字符a的字符串字符串结束标志:‘、〇’(由系统自动添加)注意:①"a"与‘a’不同!(输出结果相同)②C++语言中无字符串变量!③不能把字符串常量赋值给字符变量!例如:charc;c="a";X④统计字符串长度时,不计字符串结束标志。例如:"abed”的长度为4,而在内存中实际存放是:abcd\Op/195.枚举常量把变量的值ーー列举,变量的值只能取其中之一枚举类型的定义:形式1:enum枚举类型名{元素1,元素2,…,元素n};enum枚举类型名枚举变量名1«枚举变量名2,•••;例:enumcity{上海,北京,南京,广州,天津};//city为枚举类型名enumcitycityl,city2;//cityl,city2为city枚举类型的变量名形式2:emim枚举类型名{元素1,元素2,…,元素n}枚举变量名L枚举变量名2,…;例:enumcity{上海,北京,南京,广州,天津}city1,cyty2,city3;形式3:可以直接定义枚举变量,而不定义枚举类型名例:enum{上海,北京,南京,广州,天津}cityl;枚举类型的使即例:#include*iostream.h*enumcity{Shanghai,Beijing,Nanjing,Tianjin=5,Guangzhou};voidff(enumcityx){switch(x){case0:coutく、Shanghai

13";break;case1:coutくく“Beijing

14";break;case2:cout«"Nanjing

15";break;case5:cout«"Tianjin

16";break;case6:coutくく“Guangzhou

17";break;default:coutくく"非法城市!

18”;voidmainO{enumcitycl,c2,c3,c4;inti=7;cl=(enumcity)i!〃不能:cl=i;

19c2=Nanjing;c3=(enumcity)5;c4=Shanghai;/・枚举变量的赋值:只能为列举元素之一・/ff(cl);ff(c2);ff(c3);ff(c4);cout«cl«*"«c2くぐ・«c3«**«c4«endl;}/・执行结果:非法城市!NanjingTianjingShanghai7250*/枚举变量的使用说明:1.先定义枚举类型,再定义枚举变量,然后使用变量2.枚举元素是常量,不是变量,故也称枚举常量;所以不能对枚举元素进行赋值上例中,不能:Shanghai=Beijing;3.枚举元素是常量,其常量值不是列举的“内容”,而是定义时的次序号:0,1,…,n4.枚举元素值在定义时可以“人为”指定,上例中:Tianjin=5.此后的元素均为6,7,…上例中:枚举元素Shanghai的值为0,Beijing为1,Nanjing为2,Tianjin为5,Guangzhou为65.枚举变量的值只能取定义枚举类型时所列举的元素之一:例:c2=Nanjing;6.尽管枚举元素有值,但此值并不是整型值,所以不能把整型数赋值给枚举变量:不能:cl=5;只能:cl=(enumcity)5:/・强制类型转换・/7.枚举值(枚举元素)不是字符串8.枚举值可进行逻辑判断比较运算:上例中,if(cityl=Shanghai)if(city2>Nanjing):以序号值进行判断比较2.5常量定义(const常量)符号常量:用ー个标识符代表的常量,即:在程序中用#define命令定义某个符号所代表的常量。例如:^defineW“女,,SdefineM“男”#definePRICE123.789注意:①一旦定义了某个符号代表一个常量,则该符号在其作用域内就表示这个常量。例如:x=PRICE*0.8;②符号常量不是变量,所以,在其作用域内不能被赋值!例如:PRICE=123.012;X③为提髙程序的可读性,符号常量一般用大写表示。const常量:冻结变量例:constdoublepi=3.14159265;注意:变量一旦被const限定,就变成不能改变值的常量了;因此,const常量必须在定义时赋初值,并且const常量不能作左值!符号常量和const常量的区别:符号常量并不是变量,仅仅通过预编译命令进行“替换”,而const常量是占有内存的被“冻结”了的变量,C++中使用const常量而不提倡用符号常量。2.6I/O流控制头文件:^include*iostream,h*

201.I/O控制流的书写格式I/O控制流:输入或输出的字节序列(字符序列)操作符:《向输出流"cout"中插入字符»向输入流"cin”中抽取字符实际上,くく、>>是重载操作符cout:C++预定义的标准输出设备cin:C++预定义的标准输入设备作用:》:用从标准输入设备上所接收到的数据去更新操作符つ〉”右边的对象«:用操作符"«"右边的内容输出到标准输出设备上例:以默认的格式进行输入输出:coutくく“Howareyou!*;cout«a[0]«"*«a[l]«endl;〃或者:cout«a[0]«""«a[l]«,Xn*;cin»x;cin»a»b»c;2.使用控制符进行输入输出控制符P/23使用控制符:p/23〜p/27例:#include#include〃格式控制符voidmain()〃以指数形式输出:{cout«setiosflags(ios::scientific)<<9999.999«endl;}3.控制浮点数值的显示控制符:setprecision(n):n控制显示浮点数的数字个数(系统默认:有效位6位)在用定点表示的输出时:n表示小数位数在用指数形式输出时:n表示小数位数4.设置值的输出宽度控制符:setw(n)说明:仅仅对下一个数值的输出有效如果实际位数>n,按实际宽度输出默认宽度〇,即按输出数值的表示宽度输出5.输出8进制和16进制数dec:10进制oct:8进制hex:16进制开include

21voidmainO(intnumber=1001;coutくく“Decimal:"«dec«number«endlくぐHexadecimal:"«hex«number«endl«"0ctal:"«oct«number«endl;)1.设置填充字符setfillC填充字符’)^include♦♦includevoidmainO(cout«setfillC**)«setw(2)«21«endl«setw(3)«21«endl«setw(4)«21«endl;coutくくsetfill/Z恢复默认设置}2.左右对齐输出setiosflags(ios::left)和setiosflags(ios::right)♦♦include♦♦includevoidmainO{cout«setiosflags(ios::right)«setw(5)«1«setw(5)«2«setw(5)«3«endl;cout«setiosflags(ios::left)«setw(5)«1«setw(5)«2«setw(5)«3«endl;}3.强制显示小数点和符号I/O输出流对2.0以2显示,如果要输出小数,则用setioflags(ios::showpoint)控制符如果要输出正号,则用setioflags(ios::showpos)控制符

22♦♦includettincludevoidmain(){cout«10.0/5«endl;cout«setiosflags(ios::showpoint)«10.0/5«endl;)2.7函数printfQ和scanf()2.7.1.格式输出函数:printf()形式:printf(“格式控制串”,输出实参列表])功能:按指定的格式输出数据例如:printf(“上海交通大学:男生紀人,女生%d人”,n,w)说明:输出实参列表中如果有多个参数,则用逗号分隔实际上,printf()函数的格式为:printf(实参1,实参2实参n)格式说明:由字符和格式字符组成格式字符:d、〇,x、u、c、s、f、e、g和附加格式说明符P/28-30说明:格式控制串中,除格式说明外,有什么输出什么注意:①数据类型应与格式说明匹配,否则出错(但编译通过)②格式说明个数应与参数列表中的个数相同,且次序对应:.如果输出参数列表中的参数个数大于格式说明数,则参数列表中后面的参数值不被输出.如果格式说明数大于输出参数的个数,则多出的格式说明会导致输出随机数③格式说明串中可以用转义字符,例如:

23④如果要输出字符’%',则在格式串中的对应位置处写:%%⑤不同的系统在执行格式输出时,可能会小有差别⑥1用于长整型输出,如果应该长整型数用%d格式输出而不用%Id格式,则编译通过,执行时输出的数出错,且在其后面的参数值均错⑦缺省情况下,输出是右对齐、前补空格,但用附加格式说明符,将左对齐、后补空格2.7.2.格式输入函数:scanf()一般形式:scanf(格式控制串,地址列表)功能:从标准输入设备接受输入的任何类型的多个数据其中格式控制串与printfO函数的格式控制串类似格式符:P/31注意:①变量的地址列表,而不是变量名②数组变量的名就是该数组的地址,不必加’&,③格式控制串中,除格式说明外的所有字符,在输入时必须对应地输入@%lf:double型输入⑤用格式%c时,空格、转义字符均有效;用格式%s时,接受的字符以输入的非空字符开始至空字符或回车符止;以回车符开始执行接受输入的操作

24⑥输入数值时不能规定精度⑦输入数值时,遇非数值字符自动认为输入结束,遇宽度结束⑧如果定义输入的宽度,则输入时必须小于等于宽度;否则,如果后面有其他输出数据,这些数据值将全部出错:例:^include"stdio.h"voidmainO{intxl,x2,x3;chara[10];scanf("%2d,%3d,%d”,&xl,&x2,&x3);printf("xl=%dx2=%dx3=%d

25”,xl,x2,x3);scanfa);printf("a[10]=%s”,a);}/・文件名:scanf函数.exe如果输入:111,2,34567则输出:xl=Ux2和x3的值出错而a[10]=l,2,34567*/例:#include*stdio.h*voidmainO{inta[10],i;printf(”请输入10个整数:'n");for(i=0;i<10;i++)scanf("%d”,&a[i]);for(i=0;i<10;i++)printf("

26a[%d]=%d”,i,a[i]);)/*执行1:输入:1234567890执行正确执行2:输入:1,2,3,4,5,6,7,8,9,0执行不正确・/说明:对于用循环进行输入,之间用空格分隔例:#include"stdio'h”voidmainO{doublea;printf("请输入1个数:");scanf("%lf",&a);printf("

27a=%f

28",a);)说明:对于double型,输入时应用%If;如果用%f则出错对于double型,输出时用%f即可,系统会自动判断3表达式和语句学习目标:1.理解表达式和语句的概念2.掌握表达式中各种运算符的功能与特点3.明白产生副作用的原因

291.1表达式1.表达式概述表达式:操作符、操作对象组成的符号序列例如:2+3+(5*§izeof(iiK))/3452.左值和右值p/34左值:左值表达式简称左值,能出现在赋值运算符左边的表达式即,表示一个对象标识(有确定地址的对象)的表达式称为左值表达式右值:只能出现在赋值表达式右边的表达式(例,常量只能作右值)说明:左值既可以出现在赋值运算符的右边,又可以出现在左边。inta=3;//a是变量,所以a是左值constintb=4;//b是常量,所以b不是左值表达式可产生左值、右值或不产生值inta;(a=4)=28;//a=4是在值voidf(){return;}〃函数声明,函数声明本身不是表达式,对函数的调用是表达式,它不返回任何值,即不产生任何值。3.操作符的优先级和结合性p/35第一次出现的是单目运算符,第二次出现的是双目运算符4.语句与块C++语言中,除了控制语句、函数调用语句外,几乎所有的操作都是通过表达式进行的。语句以分号(;)结束

30C++语句分成6大类:(声明语句控制语句《r1if()〜else〜for()〜while()〜do〜while()continuebreakswitchgotoreturn(条件语句)(循环语句)(循环语句)(循环语句)(结束本次循环的执行)(终止switch或循环语句的执行)(多分支选择语句)(无条件转向语句)(从函数内返回语句)函数调用语句函数:例:printf("ok”);表达式语句空语句:;:表达式:例:a=3;x+3;5+5;7;1复合语句:用・对花括号把若干条语句括起来成为一条语句(语句块)说明:ー对花括号后面的分号可以不写,但是复合语句内的最后・条语句的分号必须!例:合法语句:4;a;a+l-7;a=l;非法语句:如果a=l3=a+2;5(7+a);a+6=7;a-a=O;C++程序书写规定:一行可写多条语句,一条语句可写多行(行尾加转移字符:'V,表示连行)注意:输入源程序时中、英文要及时切换,例如,中文的分号与英文的分号不是同一个字符说明:C++程序中的注释部分不是语句,两种注释方法:①用/**/括起的内容,不管是否换行,均是注释②用〃开头,至本行尾的内容是注释1.2算术运算和赋值1.基本运算符:+:加法或正号-S减法或负号*:乘法/,除法%:模(整除取余,操作符两边的操作数必须为整型数)说明:两个整数相除,结果为舍去小数部分、截取整数部分;但是,如果有一个操作数是负数,则不同的机器可能有所不同,大多数采用“向零取整”法。

311.复合运算符+=-=♦=/=%=a=a+6与:a+=6等价注意:a*=b+c应:a=a*(b+c)(x=max(5,7))+=3;2.算术表达式、运算符的优先级和结合性1.算术表达式由算术运算符、括号、操作数按语法规则相连接的式子操作数即操作对象:常量、变量、函数等例:a*b/c-25+'a'-(18*c+b)+max(a,b)2.算术运算符的优先级和结合性P/35规定:优先级先括号,再先乘除、模,后加减结合性从左到右结合性即结合方向:当ー个运算对象二侧的运算符级别相同时,规定的处理原则例如:c-a+b操作数a的两边的运算符相同,则先进行c-a操作除1目、3目、赋值运算符外的操作符的结合性均是从左到右3.溢出进行算术运算时,很可能溢出结果。发生溢出是由于ー个变量被赋予一个超出其数据类型表示范围的数值。shortintweight=42896;//weight=-226404.3算术类型转换1.自动转换C++遇到两种不同数据类型的数值进行运算时,会将两个数作适当的类型转换,然后再进行运算。1.字符型、整型、实型之间可以进行混合运算其中字符型数据以ASCH码的十进制数参与运算2.运算时,不同类型的数据要先转换成同一类型,然后进行运算3.转换规则:P/38的图3-1类型转换由系统自动完成例如:如果:inti=9,ii;long1=123;floatf=9.9;doubled=9.9;则:l+'a'+i*f-d/5运算结果为double型注意:①char、short型数据参加运算,系统自动将其转换成int型,然后进行运算②float型数据参加运算,系统自动将其转换成double型,然后进行运算③如果负的int型数据与无符号数进行运算,则负数作为无符号数进行运算:#include*stdio.h"voidmain(){inta=-l;

32unsignedb=0;printf("%d%u

33*,a+b,a+b);}/・输出:-14294967295*/说明:-1的补码为:1111111111111111该码的无符号的十进制值为42949672951.强制转换强制类型转换符:(类型)将一个表达式的值转换成某个类型格式:(类型名)(表达式)说明:①括号必须,但是,如果表达式是单个操作数,其括号可以省例如(int)x(int)(x+y)②一般,系统对操作数自动进行类型转换,但如果:a%b要求a和b都是整型,如果不是,必须先进行转换:(int)a%b(int)a%(int)b③转换后只得到ー个中间变量,被转换的变量的类型不变2.4増量和减量自增自减运算符3.自增:++++i:先加1后使用i++:先使用后加1例:i=3;jl=++i;jl=4相当于执行:i=i+l;jl=i;j2=i++;j2=3相当于执行:j2=i;i=i+l;2,自减:一—i:先减1后使用i一:先使用后减1例:i=3;jl=-i;jl=2相当于执行:i=i-l;jl=i;j2=i—;j2=3相当于执行:j2=i;i=i-l;注意:①自增自减只能用于变量②结合方向:自右至左例如:a=-i++;如果i=6,则a=-6,该语句执行完毕,i=7;③常用于循环语句中的循环变量和指针变量中有关表达式使用的说明C++语言的表达式使用相当灵活,所以经常会出现ー些问题1.表达式中含有自增自减运算符例:如果i=3;表达式(i++)+(i++)+(i++)的值为9,该表达式运算毕,i的值为6所以:a=(i++)+(i++)+(i++);b=i;a的值为9,b的值为62.C中有单目运算符和双目运算符,当难以确定时,编译时C++尽可能多地按自左而右地组织运算符例:i+++j;编译时认为:(i++)+j;

342.在调用函数时,实参的求值顺序视机器系统而定,大多数的系统是右一左例如:i=3;cout«iくぐ・«(i++);左f右:输出:3,3右f左:输出:4,33.5关系与逻辑运算1.关系运算符和关系表达式关系运算符和优先级6种关系运算符:<<=>>===!=I檄(7级)同级(8级)关系表达式:用关系运算符把操作对象按语法要求联系起来的式子被连接的对象可以是常量、变量、表达式。其中表达式可以是逻辑、赋值、关系表达式关系表达式的值{:ニニニ麒:聚关系表达式的值为逻辑值(真/假),可以参加运算例:如果:a=lb=2c=3①d=a>b==c>a+5Id=(a>b)——(c>(a+5))结果:关系表达式(a>b)=(c>(a+5))的值为“真",所以:d=l②d=7/2+a>c+l=b>c-5Id=((7/2+a)>(c+1))=(c>(a-5))结果:关系表达式((7/2+a)>b)=(c>(a+5))的值为“假",所以:d=02.逻辑运算符和逻辑表达式逻辑运算ーf逻辑判断3种逻辑运算符:&&逻辑表达式:用逻辑运算符把关系表达式或逻辑量连接起来的式子逻辑量:常量、变量、及算术、逻辑、赋值表达式逻辑判断真非〇:逻辑表达式的值为1假0:逻辑表达式的值为〇a&&b:a和b都为“真”时,表达式逊殳的值为“真”,否则为“假”a||b:a和b都为“假”时,表达式allb的值为“假”,否则为“真“

35!a:a为“真”时,表达式里的值为“假”,否则为“真”例:①a=5>3&&28<4-!0Ia=((5〉3)&&2)II(8〈(4-(!〇)))1&&2II8C(4T)1II0表达式a=5>3&&2||8<4T0逻辑判断结果为“真”,所以该表达式的值为1,所以a=l。②如果:a-1b=96c=3d=a='a*>b+!'O"<1&&c==3||c>a&&!b==b++Id=a=((('a'>(b+(!‘0')))〈1)&&(c==3))||((c>a)&&((!b)==(b++)))(97>96<1)&&1II1&&(0==96)〇&&1II1&&〇该逻辑表达式的判断结果为“假”,其值为:0,所以:d=a=O。3.6if语句逻辑判断语句1.3种形式①if(表达式)语句②if(表达式)语句1else语句2③if(表达式D语句11elseif(表达式2)语句2'[if(表达式)语句•elseif语句elseif(表达式n)语句nelse语句n+1丿注意:①表达式左右括号必须要②凡是“语句”,后面必须有分号”;③第3种形式可以理解成是第2种形式的嵌套2.if语句的嵌套即:上述3种形式中的“语句”之一是if语句,就是if语句嵌套例1:某商场优惠顾客:购买金额大于等于500元的8折,大于等于300元及500元以下的9折,300元以下的全部9.5折;编写计算实际应付金额的程序:程序:#include*stdio.h"voidmain(){floatx;printf("请输入总金额:つ;scanf&x);/*如果输入500*/if(x>=500)x=x*0.8;/・符合条件,执行结果:x=400♦/if((x>=300)&&(x<500))x=x*0.9;/・此时x=400,符合条件,执行结果:x=360*/if(x<300)x=x*0.95;printf("

36应付金额:%f

37",x);/・输出:360*/getchar();getchar();)/・文件名:if语句一例1ー错误

38注意:此程序有毛病:①应付金额变量名不应与x同名!②输入300,则输出:256.5原因:变量x的值被改变和比较时的精度误差・/改进后的程序:#include*stdio.h"voidmain(){floatx,y;printf("请输入总金额:つ;scanf&x);if(x>=500)y=x*0.8;if((x>=300)&&(x<500))y=x*0.9;if(x<300)y=x*0.95;printf("

39应付金额:%f

40',y);getchar();getchar();)/・缺点:一旦执行了,后面的if语句就不应再判断了,再次改进:*/再次改进后的程序:#include*stdio.h"voidmain(){floatx,y;printf("请输入总金额:つ;scanf("%f",&x);if(x>=500.0)y=x*0.8;〃对于两个浮点数,无法精确判断是否相等elseif((x>=300.0)&&(x<500.0))y=x*0.9;elsey=x*0.95;printf("

41应付金额:%f

42',y);getchar();getchar();}/・文件名:if语句一例1♦/例1.对任意输入的3个数,按大小顺序输出:程序:#include"stdio.h"voidmain(){floatxl,x2,x3,x;printf(“请输入3个数,之间用逗号分隔:つ;scanf(〃%f,%f,%f”,&xl,&x2,&x3);if(xl

43”,xl,x2,x3);3.6条件运算符格式:表达式1?表达式2:表达式3运算规则:如果表达式1为“真”,整个表达式的值取表达式2的值,否则取表达式3的值例:①x=3>4?4:5/2x=((3>4)?4:(5/2))x=2

44②如果a=4:a=a*5,a*4,a==4?a/2:++aIa=a*5,a*4,(a=4?a/2:卄a)执行结果:表达式a=果5,a*4,a=4?a/2:++a的值为:21,a的值也是21如果:表达式是a=a*5,是4,a=4?a/2:++a,则执行结果为10,a的值是10③如果a=4:b=(a*5,a*4,a=4?a/2:++a)执行结果:表达式b=(a*5,a*4,a=4?a/2:++a)的值为:2,a的值是4b的值是:23.6逗号表达式1.逗号运算符,:也称:顺序求值运算符作用:连接表达式2.逗号表达式格式:表达式1,表达式2表达式n求解过程:先求表达式1,再求表达式2,…,最后求表达式n整个表达式的值为表达式n的值例:如果a=5:表达式a=3*5,a*4的值为60即:a=3*5,a*4注意:表达式a=3*5,a*4与a=(3*5,a*4)的区别例:如果a=5:表达式3*5,a*4的值为20逗号表达式可以嵌套:例:如果a=5:表达式(a=3*5,a*4),a+5的值为20即:a=3*5,a*4这时的a=15所以:a+5就等于203.9求值次序与副作用不同的编译器求值顺序不同p/49消除副作用:将一个表达式分解成多个表达式,或加括号4过程化语句即流程控制语句4.1while语句(“当”型循环结构)一般形式:while(表达式)语句P/54说明:L先判再执行

452.表达式必须有;表达式可以是常量或常量表达式,但出现“死循环”例:…while(5){…)例:求1加到100的和#include“stdio.h"voidmain(){inti=l,sum=0;while(i<101){sum=sum+i;++i;}cout«*sum=*«sum«endl;)4.2do〜while语句一般形式:do语句while(表达式);说明:先执行、后判断注意:该语句后面的分号必须要有!例:求1加到100的和^include"stdio.h"voidmainO{inti=1,sumニ〇;do{sum=sum+i;++i;}while(i<101);coutくく“sum二r«sum«endl;4.3for语句一般形式:for(表达式1;表达式2;表达式3)语句ュ可理解为:for(循环变量赋初值:循环条件;循环变量增值)语句例:求1加到100的和^include“stdio.h"voidmain(){for(inti=l,sum=0;i<101;++i)sum=sum+i;cout«"sum="«sum«endl;)说明:1.for语句中的3个表达式之间用“;”分隔2.执行过程:P/57的图5.63.3个表达式都可以省,但是分号不能省表达式1省:循环变量的初值在for语句前已赋过表达式2省:不判断循环条件出现“死循环”表达式3省:循环变量的“增值”操作在循环体中进行,否则,如果终止条件不出现,则出现“死循环”

462.表达式1在for中只执行ー次3.在表达式1中可以对循环变量赋初值,也可以利用逗号表达式对无关的变量赋初值例:for(sum=0,j=0,i=l;i<101;++i)4.表达式2一ー判断用,所以常常是关系、逻辑表达式,但也可以出现其他表达式例:for(x=l,i=0;y=x*x,x<=5;++i,++x)4.4switch语句(多分支选择语句)一般格式:switch(表达式){case常量表达式1:语句段1case常量表达式2:语句段2case常量表达式n:语句段ndefault:语句}例:ttinclude"stdio.h"voidmainO{intx;coutくぐ请输入ー个整数(可以是负数):〃;cin»x;switch(x){case1:cout«*l:

47”;coutくく"上海交通大学

48〃;case2:coutくく"2

49";case3:cout«"3

50";case4:cout«"4

51";case'5':coutくく"字符5

52";/・字符‘5’的ASCII码:53*/default:cout«"default

53";))/・执行:分别输入1、3、5、53、-1,讲解:应使用break语句・/改进后的程序:#include"stdio.h"voidmain(){intx;printf(〃请输入ー个整数(可以是负数):");scanf("%d",&x);switch(x){case5-4:cout«"l:

54";cout«"上海交通大学

55”;break;case2:cout«"2:

56";break;case3:cout«"3:

57";break;case4:cout«"4:

58";break;case'5':coutくく"字符5

59";break;/・字符’5'的ASC码:53*/default:coutくく“default

60";break;}/Z执行:分别输入1、3、5、53、-1说明:①每个语句段可以由多条语句组成,而不必加花括号②switch(表达式),括号不可以省:表达式可以是:常量,变量,关系、逻辑、算术、赋值表达式,但是表达式的值必须是整型或字符型③default可以不写:都不符合,就什么也不做④switch语句只判断一次,作为寻找执行该语句的入口点⑤case常量表达式:的作用:仅仅作为语句标号⑥利用break语句可以跳出switch语句⑦多个case可以共用ー组执行程序段,例:

61case1:case7:case9:a=a+b;coutくく"a="くくa;break;caseI'+'p':case100:max(a,b);break;即:符合1、7、9的情况,均执行同一段语句:符合‘a'+'p'和100,均执行同一段语句4.5转向语句1.break语句作用:1.中止switch语句的执行,并跳出switch语句2.从循环体中跳出,转而执行循环体的下一条语句注意:只能用于switch和循环语句中!2.countinue语句作用:结束本次循环注意:并不从循环体中跳出,除非已处于循环结束点例:…for(j=0;j<100;++j){a=a+j*j;if(j==50)coutinue;/*如果j等于50就不执行下面的语句,直接进行下ー轮循环・/cout«*a=*«a;)3.goto语句一般形式:goto语句标号;说明:①goto为无条件转向语句,只有与if语句ー起使用方可构成循环例:求1加到100的和#includeMstdio.h"voidmain(){inti=l,sum=0;loop:sum=sum+i;++i;if(i<101)gotoloop;coutくくsum="くくsum;}③应该禁用goto语句(不符合结构化原则)4.6实例例1:P/66用公式:旦=iー丄+丄_丄4357求n的近似值,直到最后一项的绝对值小于:10-6

62ハ垢n111111TjVT:=11规律:①可以看作:4a„a,a2a3a4a,a.=5x(a1+2)当i二偶数时,s取1;i二奇数时,s取T(s=l或s=-l)②特殊情况:〃_)以。ー丄程序:#include"stdio.h"voidmain(){ints;floata,pi;for(s=l,a=l,pi=0;;a=a+2){pi=pi+s/a;s=~s;if(l/a^defineN30voidmain(){charc;inti,n,num[N]={0,1,1,1};do{coutくく"、n

63请输入年数(大于3、小于30):";do{cin»n;if(n<411n>29)coutくく"必须输入大于3、小于30的数,请重新输入:";}while(n<4||n>29);for(i=4;i<=n;i++)num[i]=num[i-l]+num[i-3];coutくく"

64第"くくnくく"年共有"«num[n]«"头母牛、n";coutくく"、n继续?(Y/N):cin»c;}while(c=yIIc=,Y,);)//2:用递归实现#includeintproduce(intn){if(n<4)return1;elsereturn(produce(n-1)+produce(n-3));}voidmainO{intn;charc;do{coutくく"、n

65请输入年数(大于3、小于30):";do{cin»n;if(n<4||n>29)coutくく"必须输入大于3、小于30的数,请重新输入:}while(n<4||n>29);coutくく"、n第"くくnくく"年共有"«produce(n)«"头母牛、n";coutくく"、n继续?(Y/N):";cin»c;}while(c='y'||c='Y');

66}

675函数5.1函数概述程序功能模块程序子程序C++语言:程序函数程序结构:例:编写ー个对某个正整数有关的处理程序注意:层次结构、函数调用关系、函数返回值说明:1.源程序文件:ー个源文件是一个编译单位,不是以函数为单位进行编译的2.C++程序由一个或多个源文件组成;分多个文件可以提髙编译和调试的效率3.主程序只能有一个,程序执行自主程序开始,由主程序结束而结束4.函数必须定义,定义时各函数相互独立:不能嵌套定义:除主函数外,函数间可以相互调用5.函数分类:从用户角度:库函数、自定义函数从形式:无参函数、有参函数5.2函数原型p/78函数声明就是函数原型函数的声明和函数的定义,在返回类型、函数名、参数个数、参数类型、及参数顺序上必须完全一致,否则编译时出错C:函数抽象用于表达问题求解中的一个过程C++:函数抽象主要用于定义类上的操作接口5.3全局变量与局部变量1.程序的内存区域P/81图5-2S代码区、全局区、堆区、栈区2,全局变量在函数外部定义的变量称全局变量作用域:从被定义的位置起,至文件结束处止说明:全局变量在程序执行的整个过程中,占用固定的内存单元具有初始值可以被在其定义后的所有函数共同使用(解决“一个函数只能返回一个值”的问题)在同一源文件中,如果外部变量与局部变量同名,贝リ:在局部变量的作用域内,同名的全局变量不起作用

683.局部变量只在某ー函数内部定义的变量称局部变量,局部变量存放在栈区作用域:只局限于本函数内说明:不同函数的局部变量可以同名形参是局部变量除本函数外,其他函数一概不能使用复合语句中的局部变量:复合语句可以看成是“程序块”,在其内部可另行定义变量分程序局部变量这种变量出了该复合语句就无效一般:在复合语句中的循环变量可以在复合语句中定义例:#include*stdio.h*voidmainO{inti=0,j=9;{intj=0;//j的作用域:自此起,到本复合语句结束处止printf("复合语句j=%d

69”,j);)printf(*j=%d

70*,j);for(intk=0;k<5;++k)〃k的作用域:自此起,到本函数结束止printf("k=%d",k);printf(*

71k=%d

72*,k);}/・执行输出结果:复合语句j=0j=9k=0k=lk=2k=3k=4k=5*/5.4函数调用机制栈函数的整个过程就是栈空间操作的过程:保护调用函数的运行:入栈建立被调用函数的栈空间传递参数将控制转给被调用函数……P/835.5静态局部变量静态局部变量:局部变量定义时,前面冠以static注意:静态局部变量只在函数第一次被调用时进行初始化可见性:本函数内存储类型:auto自动(动态,局部变量)static静态(可以全局,也可局部变量)\用作定义register寄存器(形参,局部变量)Jexternーー外部的全局变量仅作说明C++规定:①每个变量和函数有两个属性:存储类型和数据类型,并必须加以定义:存储类型数据类型变量名列表;②局部变量的存储类型缺省,默认为:auto型③外部变量:指本文件外的全局变量如果外部变量的定义出现在本源文件、且在引用前,则引用时可以不说明,否则必须说明外部变量的定义:只定义一次,且在函数外定义5.6递归函数递归调用:直接或间接地调用自己直接递归调用:在函数f中调用函数f例如:…voidf()

73{…f();),间接递归调用:函数f调用函数ff,而函数ff调用函数f注意:要有终止递归调用的条件!例“汉诺”问题汉诺问题:a针上有从小到大排列的n个盘,要求把这些盘全部搬到c盘上,可以利用空的B针;但是:每次只能搬动ー个盘,且在搬动时每个针上必须保持盘从小到大的排列次序。分析:设子函数:voidmove(源针,目标针):把ー个盘由源针搬到目标针voidhanoi(盘数,源针,借助针,目标针):把参数“盘数”指定的这些盘,通过借助针,由源针搬到目标针分析:I输入盘子数:nI调用hanoi()函数I结束hanoi()函数:(借助b针,把a针上的所有盘子ーc针上)其中:①可以把(n-1)个盘子再当作n个盘子:再分成最大的1个盘子和(n-1)个进行上述的移动,直至n=l个(递归)②完成“移动”操作的函数:voidmove(源针,目标针)“汉诺”函数:hanoi(盘子数,源针,借助针,目标针)③(nT)个盘子:借助a,bc程序:#includeiostream,h”voidmove(chara,charc){staticinti;i++;cout«i«*:"くくaくく"f"«c«endl;}voidhanoi(intn,chara,charb,charc){if(n=l)move(a,c);else{hanoi(n-1,a,c,b);move(a,c);hanoi(n-1,b,a,c):)voidmainO{intnum;coutくぐ请输入盘子数:“;cin»num;coutくく“按、"汉诺塔ぐ的规则,把"くくnumくく"个盘子从a针搬到c针的步骤是:

74";hanoi(num,'a','b','c);}/・如果输入4:(如果输入5,则执行31步)按“汉诺塔”的规则,把4个盘子从a针搬到c针的步骤是:1:a-b

751:a—c2:bc3:a—b4:c-a5:c-b6:a-b7:afc8:b~c9:b—a10:c—a11:b—c12:ab13:a—c14:b-c*/5.7内联函数inline:也称内置函数、内嵌函数目的:减少开销、提髙效率在编译时,象对待“宏”一样进行替换,程序运行时没有函数调用过程和函数返回定义、声明时:在前面冠以“inline”即可说明:⑴如果被调用函数定义在被调用之前,且定义时冠以inline,则以后每次被调用均作内联函数处理。如果被调用函数定义在被调用之后:①定义时没有冠以inline:如果在被调用前声明过该函数,且声明时冠以inline,则以后每次被调用均作内联函数处理②定义时冠以inline:如果在被调用前声明过该函数,但声明时没有冠以inline,则被调用均不作内联函数处理即:必须声明成“内联”的,或无声明、但定义成“内联”的⑵内联函数内不能出现switch、循环语句,否则报错,作普通函数进行调用。例:#includeinlinevoidabc(){for(inti=l;i<10;++i)cout«i«endl;}voidmainO{coutくく“start.…"«endl;abc();cout«"end..."«endl;}该程序能够通过编译,但必须注意在内联函数中不应该出现循环语句。⑶递归函数不能被定义成“内联”函数⑷内联函数不能进行“异常接口声明”,例如,被除数为0的“异常声明”⑸对常被调用的小而简单的函数进行“内联”。5.8重载函数p/951.”重载“概念面向对象系统的3大特性之一的多态性就是通过重载实现的重载:即同名不同义,在不同的情况下可表现出不同的“行为”重载包括:函数重载:多个函数同名,但执行的操作和操作对象不同操作符重载:ー个运算符,可进行多种不同含义的解释,进行不同的操作问题的提出:例如,比较大小:2个整数比较、2个浮点数比较在C++中必须逐个定义不同名的多个函数

76希望:由系统自动判断,用户只要记住函数名即可重载:写多个同名函数,由系统根据操作数自动判断究竟调用哪个函数1.匹配重载函数的顺序P/93的原则:按如下先后顺序:1寻找ー个完全匹配,找到就调用2通过内部转换、然后寻找严格匹配,只要找到就调用3通过用户自己定义的转换寻找严格匹配,找到就调用例:/93〜942.使用说明1.重载函数至少在参数个数,参数类型、或参数顺序上有所不同,仅返回类型不同不行2.不能用typedef定义的类型名来区别重载函数中的参数类型,因为“编译”时不区分其差别3.同名函数应具有相同的功能例:〃5.8节一般函数名重载p/78#include#includeintadd(intx,inty){returnx+y;}doubleadd(doublex,doubley){returnx+y;}intadd(intx,doubley){returnint(x+y);}doubleadd(doublex,inty){returnx+y;}voidmain(){coutくくadd(99,88)くく”cout«add(99.9,88.8)«"cout<

776程序结构多文件结构6.1外部存储类型extem声明:仅声明是本文件外的变量或函数,不是定义外部变量或函数外部变量的定义:只定义一次,且在函数外定义:定义格式:与全局变量的定义格式同外部变量的说明:可以说明多次说明格式:extern外部变量类型变量名列表;例:externinta,b;externcharx,y;6.2静态存储类型1.静态全局变量全局变量定义时,前面冠以static作用:全局变量的作用域是整个程序,对于多文件程序结构,ー个文件的全局变量可以被另一个文件使用,但静态全局变量的作用域被限定在本文件内,别的文件不能使用2.静态函数函数定义时,前面冠以static作用:函数的作用域是整个程序,对于多文件程序结构,ー个函数可以被另ー个文件使用,但静态函数的作用域被限定在本文件内,别的文件不能使用。3.3作用域作用域:标识符在程序中的有效范围1.局部作用域局部作用域:自定义的位置起,至所在的语句块尾或函数尾止例:#includevoidmain(){for(inti=0,x=20,y=30;y<200;i++)//i自此至本函数尾有效{intz=i+l;//z自此至本语句块尾有效cout«(y+=x)«endl;

78cout«i«endl;〃合法cout«z«endl;//error:z没有定义1.函数作用域ー个标识符不管在函数的什么地方定义,自函数的起始点起,至函数的终止点都有效,则此标识符具有函数作用域。语句标号是唯一具有函数作用域的标识符p/108例题:可以使用出现在后面的语句标号标识符2.函数原型作用域指:函数声明(不是定义)中的形参标识符的作用域仅仅在函数原型中例:intmax(intx,inty);x=100;//error:x没有定义3.文件作用域文件作用域:本文件内有效,也称全局作用域全局变量(包括静态全局变量)、静态函数具有文件作用域4.4可见性可见即可用,可见性与作用域相一致注意:内部标识符“支配”外部同名标识符局部标识符“支配”全局同名标识符(解决办法:加域限定符S!进行引用)5.5生命期1.静态生命期与程序运行期同函数、全局变量、静态局部变量都具有静态生命期2.局部生命期非静态的局部变量具有局部生命期如果不进行初始化,其值不确定

791.动态生命期动态分配的对象具有动态生命期:如果不释放(即收回),则直到程序运行结束,生命期オ结束2.6头文件以.h为扩展名的文件,用»include命令包含进来适宜放在头文件中的信息:p/1133.7多文件结构ー个大程序可以由多个源文件组成,每个源文件可以进行独立编译p/116图6-24.8预编译处理编译预处理:C++的主要功能在程序中通过预处理命令实现,不是C++的语句C++编译系统:先对程序中的特殊命令进行预处理,然后把预处理结果和源程序ー起进行常规编译处理(词法、语法分析,代码生成,优化等)提供3种预处理功能:宏定义]文件包含卜均以“が’开头条件编译J1.#include命令P/116作用:把指定的源文件(或:头文件)的全部内容包含到当前文件中一般形式:includeく文件名〉include”文件名”形式1:直接按系统标准方式检索文件目录形式2:在当前源文件的目录中寻找,找不到再按系统标准方式检索其它文件目录说明:①一条命令只能包含进ー个文件②被包含进来的文件的次序,就是该条包含命令的次序③如果嵌套包含文件,则涉及到的全部文件均应包含进来,且最深ー层被包含的文件所对应的包含命令应在最前面例如:文件3中包含文件2,文件2中又包含文件1,应该:^includettincludettinclude④被包含的文件的扩展名:.h.c.cpp⑤被包含后的所有文件均成为ー个文件,并作为一个文件进行编译、连接,得到一个目标文件、ー个可执行文件;但是:♦作为源文件,依旧相互独立存在•原各文件中的全局静态变量就成为整个文件的全局静态变量了(不必冠以extern)

801.#define命令注意:在C++中已经被const定义所代替#define、ttundef命令宏定义:宏代换作用域:自#define起,加ndef或文件结束止注意:一次命令定义ー个宏;是命令,不是语句;但可以出现在函数中不带参数的宏定义:作用:用指定的宏名(符号常量)代替ー个字符串形式:#define宏名字符串例:#define^define例:…#defineftdefineName上海交通大学Namel“上海交通大学”Name上海交通大学Namel“上海交通づ注意:两者不同!voidmain(){charn[20]=Name;charm[20]=Namel;…)预处理后为:voidmain(){charn[20]=上海交通大学;非法语句charm[20]=“上海交通大学”;合法语句)说明:①一般用大写标识宏名②宏名代表ー个字符序列,预处理时不检査其合法性,在编译被宏展开后的源程序时进行合法检査③宏定义不是语句,行末不必加分号,如果加了,则一起转换④在宏定义中,可以利用已定义的宏⑤用双引号括起的为字符串常量,在双引号中出现的宏名一概不替换带参数的宏定义:作用:除进行字符序列替换外,再进行参数替换一般形式:4define宏名(参数列表)字符序列宏替换过程:用指定的字符序列替换宏名,然后用实参替换参数列表中的形参例:#defineS(a,b)a*b+a/bx=S(5,7);I2>例:例efinePi3.1415926^defineS(r)Pi*r*rx=S(a+b)*x;第一步:x=a*b+a/b;第二步:x=5*7+5/7;ftdefinePi3.1415926ftdefineS(r)Pi*(r)*(r)x=S(a+b)・シVx=3.1415926*(a+b)*(a+b)*x;x=3.1415926*a+b*a+b*x;说明:①在宏名与参数列表的括号之间不能有空格,否则被理解为不带参数的宏替换

81②“实参”与“形参”应ーー对应,无类型而言,仅替换;“实参”如果是表达式,并不进行运算③与函数的形参和实参有本质上的区别:不分配内存、参数无类型、表达式不求值、宏展开在预编译时进行(函数调用在运行时进行)④宏替换不占运行时间,只占编译时间3.条件编译命令作用:对满足条件的部分程序内容进行编译,否则不参与编译功能:便于调试判断符号常量,进行条件编译:形式1:#ifdef标识符程序段#endif作用:如果标识符被定义过(一般用#define命令定义),则编译程序段,否则不编译形式2:#ifdef标识符程序段1#else程序段2#endif作用:如果标识符被定义过,则编译程序段1,否则编译程序段2形式3:#ifndef标识符程序段#endif作用:如果标识符没有被定义过,则编译程序段,否则不编译形式4:#ifndef标识符程序段1#else程序段2#endif作用:如果标识符没有被定义过,则编译程序段1,否则编译程序段2判断表达式,进行条件编译:形式1:#if(表达式)程序段#endif作用:如果表达式成立(表达式为“真”)则编译程序段,否则不编译形式2:#if(表达式)程序段1ttel.se程序段2#endif作用:如果表达式成立则编译程序段1,否则编译程序段2说明:①只对在判断范围内的程序段进行条件编译,其它的程序部分均编译②不编译——不可能执行③省编译时间,减少目标程序的长度,便于程序移植例:#include*stdio.h*ttdefineStudent0voidmainO(ttifdefStudentprintf("处理学生信息...

82");(#if(Student)printfC处理小学生信息...

83");#elseprintfC处理大学生信息..・'n");Aendif)#elseprintf("处理教师信息.•.、n”);#endif

84)/・改成:#defineStudent1再执行一次然后,把#defineStudent1用注释括起再执行ー次・/7数组数组:有序的同一类型的数据的集合说明和规定:①数组属于构造类型,数组中的所有元素必须属于同一类型②数组元素的表示:数组名[数组下标],例如:a[0],a[l],a[i],a[i+9]下标:数组元素到数组起始位置的偏移量p/120③先说明后使用④只能引用数组元素,而不能引用数组。例如:intj,a[100];j=a[5]+a[0];j=a;X⑤数组元素可以被赋值,也可以作为操作数出现在表达式中:a[O]=a[l+j]%j;⑥定义数组时,元素的个数必须是整型常量或常量表达式。例如:charc[50];charc[j];X⑦C++不提供数组下标越界保护⑧下标编号从〇开始7.1数组定义和使用1.定义格式:类型说明数组名[数组长度表达式]例:UdefineN200;floatf[50];inta[N*2];说明:①数组长度即数组元素的个数,数组长度表达式中不能出现变量,表达式的值必须是正整型②必须是方括号,不能是圆括号2.访问数组元素数组元素作为操作数可以参加各类操作(表达式、函数调用)注意:在使用时,方括号中可以是常量、含有变量的表达式,因为其值(必须是不超过长度的整数值)是数组下标。例:inta[10],b[7];a[0]=a[0]+b[7];Xb[6]=max(a[7],b[0]);b[7]=max(a[7],b[0]);每个元素存放ー个字符凡是字符数组均可以用整型数组来实现

851.2初始化数组在定义数组的同时进行赋初值:inta[10]={l,2,3};说明:①数组定义时不初始化,各元素的值不确定②初始值依次写在花括号中,之间用逗号分隔③初始化时可以省略长度定义,系统自动取花括号内的数据个数作为数组长度例如:inta口={0,1,2,3,4};长度为5④定义数组时可以对前面的部分元素进行初始化,但是数组的长度不能省略例如:inta[100]={ll,22,33};⑤初值可以是已赋过值的变量、含有赋过值的变量的表达式、常量表达式,例如:#include*stdio.h*voidmain(){inty=123,a[100]={y,y+5,5+55};printf(*%d%d%d

86*,a[0],a[l],a[2]);}〃执行结果:12312860说明:如果y不赋初值,编译时会警告!注意:不可以:inta[10]={l,,2,3};p/1252.3字符数组每个元素存放ー个字符凡是字符数组均可以用整型数组来实现1.字符数组定义:charc0[10],cl[2][10];2.初始化1.chara[10]={匕','k'};即:a[0]='a';a[l]='b';a[2]〜a[9]:没有初始化或者:chara[10]={uab"};BP:a[0]='a';a[l]='b';a[2]='\0';a[3]〜a[9]:没有初始化2.staticchara[10]={'a','b'};即:a[O]=,a,;a[l]=,b,:a[2]~a[9];初始化成"空"数组a是静态变量3.缺省长度定义:chara[]={匕,,,b,};系统自动判断数组a的长度为2,即:a[2]chara[]={"abw);系统自动判断数组a的长度为3,即:a[3]5因为字符串有结束标志へ(F,由系统自动加上4,初始化的元素个数大于长度,则语法出错(编译通不过):chara[2]={匕’,'b','c'};5.对于二维数组,初始化的元素先分配给〇行的各列,然后分配给1行的各列,…可以全部罗列,以逗号分隔;也可以按行进行初始化,各行用一对花括号括起,各行用逗号分隔

87例:chara[5][10]={

88",a,strlen(a));}/・如果输入"abed",输出:abed1=4*/如果用数组来存放字符串,则数组长度应定义成:字符串可能的最大实际长度+15.字符数组的输入输出ヘ〇'只作判断用,不会输出!C!利用输入输出函数以及格式符进行输入和输出:%c、%s例:#include*stdio.h*voidmain(){chara[20];scanf(.%s”,a);printf("%s

89",a);puts(a);getchar();gets(a);printf("

90

91%s

92”,a);puts(a);getchar();)/・执行3次,分别输入字符串:“123456”/“123456”/“123”"456789"/*/关于%s字符串格式输入输出的说明:①输出字符不包括へ〇,,遇第一个へ〇,结束②输入时,以非空字符起,遇空格止,以“回车”为"写入”③输入时,写数组名即可,可以不加地址符,&,(对于数组)④输出时,写数组名而不是数组元素名(对于数组:用%s格式输出)

93⑤如果一次输入(以回车符为标志),自动以空格分隔,例:chara[10],b[10],c[10],d[10];scanf('%s%s%s%s',,a,b,c,d);如果输入:Iamastudent.则"I”f数组a,"am”f数组b,a-数组c,student.ー数组d⑥输入的字符个数超过数组的长度,取等于长度数的字符数,无字符串结束标志C++:输入输出流对象cin、cout3.有关处理字符串的函数的介绍分别包含在"stdio.h”、"string』”、"ctype.h"中P/313①字符串输出函数:puts(字符数组名)例:chars[]={4tChina

94Beijing,5};/Z花括号可省:charsロ='4china

95Beijing”;puts(s);输出:ChinaBeijing注意:一次只能输出ー个字符串,不能:puts(sl,s2);X②字符串输入函数:gets(字符数组名)说明:一次只能输入一个字符串输入什么接受什么输入超过长度,则根据长度自动截止;小于长度,后面的元素补,、〇,字符数组名前不必加地址符,&,,因为数组名本身就是该数组的地址③字符串连接函数:strcat(字符数组名1,字符数组名2)//strncat(char*,char*,intn)作用:把字符数组2接在字符数组1的后面,然后赋值给字符数组1;该函数被调用结束,返回字符数组1的地址说明:数组1的长度要足够大,如果长度不够,可以执行,但运算结果出错原来数组1后面的,'0,自动取消,在连接后的字符串后自动加,'0,(如果长度够的话)④字符串拷贝函数:strcpy(字符数组1,字符数组2或字符串常量)//strncpy(char*,char*,intn)作用:把字符数组2或字符串常量拷贝至字符数组1中例:strcpy(al,a2);strcpy(a,"asdfdfhjdskhg”);注意:字符串不能直接进行赋值,例如:chara[10],b[10]={<423456789,,}:a=b:X数组1的长度必须>=数组2或字符串常量的长度拷贝时,连同字符串结束符一起拷贝至字符串数组1中例:#include*stdio.h*#include*string.h"voidmainO{chara[10]={*abcdefghi*},b[5];printf(*a:%s

96b:%s

97*,a,b);strcpy(b,a):printf(*a:%s

98b:%sl=%d

99*,a,b,strlen(b));printf(*b[4]=%cb[5]=%cb[8]=%c

100*,b[4],b[5],b[8]);getchar();J/・先执行该程序,然后把数组b的长度改成10,再执行,比较有何区别・/⑤字符串比较函数:strcmp(字符串常量1或字符数组名1,字符串常量2或字符数组名2)//strncmp(char*,char*,intn)作用:对两个字符串进行比较,然后返回比较结果:返回〇两串相等>0的整数串1>串2

101<0的整数串1〈串2说明:•从第0个元素起,逐个往后进行比较,自首次出现不同的字符就比较该字符的大小,后面的字符不予比较(不必长度一定要大)例:"abcde"和”ac",串"ac”大•比较两个串的大小,只能用函数进行,不能:串1=串2⑥求字符串长度的函数:strlen(字符数组名或字符串常量)例:strlen(a);strlen(ugfhfjgjfgjdfg^^);说明:长度不包括字符串结束标志:へ0'⑦大小写转换函数:strlwr(字符数组名或字符串常量):大写ー小写strupr(字符数组名或字符串常量):小写一大写说明:串中的非字母字符不转换注意:不同的系统所提供的库函数的函数名和功能有所不同!因为库函数本身不是C的组成部分。7.4向函数传递数组如果实参是数组,则形参不管是指针形式还是数组形式,传递的都是数组的首地址。把实参(数组首地址)拷贝给形参(数组首地址),而不是把整个数组拷贝给形参。数组元素、数组名都可以作函数的参数其中:数组名既可以作形参、也可以作实参,进行整个数组的传递而数组元素只能作实参,不能作形参(即,这时形参只能写成单变量形式,不能写成数组元素形式)例:…//error:intmax(intx[],inty[]){return(x>=y?x:y);}intmax(intx,inty){return(x>=y?x:y);}voidmain(){inta[10]={l,2,3,4,5,6,7,8,9);coutくくmax(a[7],a[9])くく“"«max(a[8],a[0])<,endl;}1.数组元素作函数的参数与变量ー样,进行“值传递”例:max_num=max(a[j],b[j]);2.数组名作函数参数不是进行“值传递”,是把数组的首地址传递给被调用函数数组名作参数时,调用函数和被调用函数的该参数都应说明成是数组,而且实参与形参都是数组名例1:求整数数组中,的最大数:ttinclude*iostream,h#defineN10voidmainO{inta[N]={l,2,3,4,5,66,7,8,9};intmax(inta[],int);cout«max(a,N);}intmax(inta[],intn){for(intm=0,i=0;im?m=a[i]:m;returnm;}例2:有N个学生,每个学生有5门课,计算各学生的平均成绩程序:#include*iostream.h"^defineN5floataverage(floatarray[],intn)//floataverage(float*array,intn){inti;floatsum=0.0;for(i=0;i

102voidmain(){floatarray[N];inti;coutくく”请输入该学生的“くくNくく“门课的成绩:

103〃;for(i=0;i

1041.二维数组的初始化例:inta[3][4]={{l,2,3,4},{l}},b[2]例]={0,1,2},c[5][5]={{1},{2}};说明:①初始化形式多样,但是总是从首元素开始分配②按行进行初始化,每行用ー对花括号括起,之间用逗号分隔③整个按顺序进行初始化:ー对花括号,无行的花括号④部分元素初始化:自每行的首元素起被分配初值⑤行维长度可省、列维长度不可省:例:inta[][5]={0,l,2,3,4,5,6,7,8,9,10};〃省略第一维大小共11个元素,系统自动判断行维长度为3,即:inta[3][5]={0,1,2,3,4,5,6,7,8,9,10};注意:不能:inta[3][4]={{1,2,3,4},{},{1})4,降维处理降维处理:在函数调用与被调用之际,把二维数组的首地址传递给形参,以达到把二维数组在被调用函数内作为ー维数组处理的目的注意:数组首地址用首元素的地址,不要用数组名例:p/1335.二维数组举例例:把一个二维数组的行、列元素互换,并存到另ー个数组中去分析:如果是ー个2X3的矩阵,则转换成3X2的矩阵即:b[j][k]=a[k][j];程序:#include"iostream.h"voidmain(){inta[2][4],b[4][2],j.k;coutくぐ请依次输入2X4矩阵元素值,每行各元素间用逗号分隔,回车后另起一行:'n";for(j=0;j<2;++j)cin»a[j][O]»a[j][l]»a[j][2]»a[j][3];for(j=0;j<4;++j){for(k=0;k<2;++k){b[j][k]=a[k][j];cout«b[j][k]«*”;)cout«*

105*;))7.6数组应用:排序快速排序港:p/137-139:书上的程序〃错•includeiostream,hvoidsort(int*a,intleft,intright);voidmain(){inta[100],max,i=0,j=0;coutくく”请输入整数序列,以ー9999结束输入,最多输入100个整数:

106";cin»a[0];while(a[i]!=-9999)

107{i++;cin»a[i];}max=i-l;sort(a,0,max);for(i=0,j=0;i<=max;i++){cout«a[i]«**;j++;if(j>=10){cout«endl;j=0;})cout«endl;}voidsort(int*a,intleft,intright){intpm,l=left,r=right,temp;pm=a[(left+right)/2];while(lpm)-r;if(l>=r)break;temp=a[l];a[l]=a[r];

108aLr]=temp;++1;-r;)if(leftpm)-r;if(l>=r)break;temp=a[l];a[l]=a[r];a[r]=temp;++1;-r;}inti=0,j=0;while(a[i]!二一9999){cout«a[i]«**;i++;j++;if(j>=10){cout«endl;j=0;}}cout«endl;if(left

109";cin»a[0];while(a[i]!=~9999){i++;cin»a[i];}max=i-1;sort(a,0,max);"/输入:123904106分析执行结果・/7.y数组应用:Josephus问题程序:♦♦include"iostream,h"♦♦defineN7voidmainO{intnum=0,p=l,a[N+l],i,number=0;for(i=0;i<=N;++i)a[i]=i;while(number

110if(num=3&&a[p]!=0){alp]二〇;num=O;number++;}++p;if(p>N)P=l;)for(i=l:i<=N;++i){if(a[i]!=O){coutくく”最后ー个获胜者的编号是:"くくendl;break;})8指针在C++中:任何变量都有地址,这些变量都可以用指针来指向并进行操作8.1指针概念1.指针类型每个数据类型都有相应的指针指针有类型,什么类型的指针只能指向该类型的对象,不能指向其他不同类型的对象2.指针变量的定义intx,y,*px,*py;charcl,c2[10],*pc;注意:在变量定义语句中,每定义ー个指针,在指针变量名前必须加’*'3.建立指针(初始化指针)操作符&:取址intx,y,*px=&x,*py=&;charcl,c2[10],*pcl=&cl,*pc2=c2;4,间接引用指针变量操作符・:取指针变量所指向的单元内的内容例:#include*iostream,hvoidmainO{intx=100,y=x+200,*p=&y;chara[10」=abcdefg*,*pc=a;coutくくyくく“"«*p«""«p«endl;cout«a«""«*pc«""«pc«endl;}/♦300300地址值

111abcdefgaabcdefg*/说明:指针变量的间接引用可以作左值5.指针变量的地址指针本身是变量,所以指针变量也有地址,指针的地址是"指针的指针”p/147-148例:^include"iostream.h"voidmain(){intx=100,*p=&x,**pp=&p;cout«x«""«*p«""«*pp«""«**pp«endl;}/*1001000x0066FDF4100*/6.定义指针和使用指针的区别定义语句中的‘*‘和'&':intx=123,*p=&x,y=*p;//intx=123,*p=&x,y=x;例:#include"iostream.h"voidmainO{intx=123,*p=&x,y=・p;〃定义指针p和使用指针p(等价:intx=123,*p=&x,y=x;)cout«x«""くく・pくく“"くくyくくendl;〃使用指针pヽ[*123123123*/7.指针的初始化即:给指针变量一个初始指向p/1498.指针类型与实际存储的匹配p/149例题讲解强调:指针所指向的变量的类型必须与指针类型一致8.2指针运算指针变量描述的是地址,是无符号量,不同于整数和无符号整数指针间的算术运算(指针相加、相乘、相除、模)均无意义!但是,在一定的条件下,指针可进行:1.两个指针变量的比较运算①当指针变量P1和P2指向某ー变量时,可以进行如下逻辑判断:pl=p2如果相等,则pl和p2指向同一变量pl!=p2如果不等,则pl和p2指向的不是同一变量②当指针变量P1和P2指向同一个数组变量时,可以进行如下逻辑判断:pl=p2如果相等,则表示指向数组的同一元素pl!=p2如果不等,则表示指向的不是同一元素Pl>p2如果成立,则表示pl指向的数组元素在p2指向的数组元素之后2.两个指针变量的减法运算(两个指针变量的加法无意义)当两个指针pl和p2指向同一数组时,可进行减法运算:

112|pl-p2|绝对值表示pl指向的对象(数组元素)与P2指向的对象之间的元素个数1.一个指针变量与整数的运算当指针指向数组时,可进行加、减一个整数的运算:P±n!从当前指向的数组元素上移或下移n个元素5.2指针与数组实参是数组,形参不管是指针形式还是数组形式,传递的都是数组的首地址。把实参(数组首地址)拷贝给形参(数组首地址),而不是把整个数组拷贝给形参。在C++中:任何可以用数组下标完成的操作,都可以用指针来实现使用指针数组可以使程序更紧凑、灵活数组的指针:数组的地址数组元素的指针:数组元素的地址指向数组的指针变量:用变量表示一个指向数组的指针对于任何ー个已经定义过的指针变量,即可以指向同类型的任一变量,又可以指向同一类型的一维数组:当指向数组时,便是数组指针,可以指向该数组中的任一元素1.指向ー维数组元素的指针(1)定义数组指针inta[10],*p=a;(或:inta[10],*p=&a[O];不可以:inta[10],*p=&a;)或者:inta[10],*p;P=a;注意:不能写成:*p=a;*p=&a[O];可以:p=a;*p=*a;p=&a[O];*p=a[O];(2)数组名与数组指针变量数组名是数组的起始地址,也是数组的第0个元素的地址所以:如果指针变量p指向数组a:inta[10],*p=a;①*p、・a、a[O]:等价②p+i1a+i)均表示a[i]元素的地址,指向元素a国③a[i]>p[i]-*(p+i)»均表示a[i]的值,就是a[i]*(a+i)-④P可以改变值,数组名不可以;即:指针变量的值可变,数组名值不可变,因为数组名本身是数组变量、而不是指针变量例:P++;合法:表示当前指针值加1,指向下一个元素a++;非法(3)数组元素的引用如果a是数组名,p是指向a的指针下标法引用:a[j]形式指针法引用:*(a+j)*(p+j)p|j]例:#include*iostream.h*voidmain()

113{inta[10]={123,11,22,33,44,55,66,77,88,99},*p=a,i;P=a+8:〃p指向a[8]p—;//p指向a[7]P=P-2J〃p指向a[5]*p=a[3];//a[5]=a[3]=33*++p=600;〃・(++p)=600;p指向a[6],a[6]=600*(a+3)=300;//a[3]=300for(i=0;i<10;i++)cout«*a[*«i<<*]=*«a[i]«**;2.数组名、数组指针变量作函数参数1.数组名和数组指针变量都是地址,作为函数参数均传递地址数组名:传递的是首地址数组指针变量:传递的是当前地址2.不管实参是数组名,还是指针变量,形参都可以定义成数组名或指针变量操作时要注意:数组元素不可越界3.指向二维数组的指针(1)二维数组元素的地址对于二维数组a:形式1:a数组首地址,第0行首地址:元素a[〇][〇]的地址a+1第1行首地址:元素a[l][〇]的地址a+2第2行首地址:元素a[2][0]的地址形式2:可以把a[0]、a[l]、a[2]看成一维数组名,所以:a[0]第0行首地址:元素a[〇][〇]的地址a[l]第1行首地址:元素a[l][0]的地址a[2]第2行首地址:元素a[2][0]的地址形式3:a[i]+j表示第i行第j列的地址:元素a[i][j]的地址如果定义二维数组inta[3][4]={{0,l,2,3},{4,5,6,7},{8,9,10,11)}:注意:①二维数组名a并不表示元素a[〇][〇]的地址,而是数组a的地址,数组a的地址就是a[〇]的地址,即是第〇行的地址;所以:a和・a不等价②a[i]中是元素a[i][0]的地址,而(a+i)表示a[i]的地址,所以:a+i和a[i]不等价(2)二维数组的指针注意:不能把ー维数组指针用于二维数组理解成:由n个元素(n为二维数组的列数)所组成的数组的指针例:inta[3][4],(*p)[4]=a;/*(*p)[4]的圆括号不能缺,否则为指针数组・/说明:①指针值可以改变,表示指针的指向改变,可以进行有意义的运算:P土n②表示地址:*pp[O]*(p+O)等价:&a[O][0]p[i]*(p+i)等价:&a[i][0]p[i]+j*(p+i)+j等价:&a[i][j]

114③间接访问:(*(p+i))[j]*(p[i]+j)*(*(p+i)+j)等价:元素的值注意:对二维数组指针p,*p是〇行的首地址:p[0];*(p+i)是i行的首地址:p[i]例!.:#include*iostream.h*voidmain(){inta[3][4]={{1.3,5,7},{9,11,13,15},{17,19,21,23}};int(*p)[4]=a,i,j;for(i=0;i<3;i++){for(j=0;j<4;++j)cout«*(p[i]+j)";cout«endl;}cout«*

115

116*;for(i=0;i<3;i++){for(j=0;j<4;++j)cout«(*(p+i))[j]«**;cout«*

117*;}}/・执行结果:13579111315171921231357911131517192123*/例2:#include"iostream.h"voidmain(){inta[6][2]={{1,3},{5,7},{9,11},{13,15},{17,19},{21,23}};int(*p)[2],i;p=a+l;/・二维数组指针p指向二维数组a的第1行首地址・/for(i=0;i<5;p=p+l,i++)cout«*p[0]«*”;coutくく"、n

118";for(p=a;p

119*»i,p[i]);)voidmain(){inta[2][3]={1,2,3,4,5,6);print(&a[0][0],6)i〃二维数组a的第一个元素的地址作函数的实参)8.4堆内存分配p/155动态内存分配,释放动态内存分配C:malloc(size),calloc(n,size))>free(指针标识符)

120堆:允许程序在运行时申请某个大小的内存空间堆内存:动态内存new、delete操作符:C++专用操作符,不必用头文件声明例:itinclude"iostream,h”^defineN100voidmain(){int*pl,*p2;pl=newint[N];p2=newint;delete[]pl;//delete[]pl,p2;deletep2;)在14章将进ー步讨论这2个操作符8.5const指针p/i59constant关键字:const作用:冻结,修饰类型描述符,得到该类型的派生类型被const的对象不能再被更新,所以在定义时必须初始化例:constinta=555,b=l;//intconsta=555,b=l;a=777;〃出错b=666;〃出错1.指向常量的指针指向常量的指针:指针指向的变量值不能变,指针本身的值可变即:对于指向常量的指针p,*p不可以再被赋值例:constinta=78,b=27;〃a,b都是常量,定义时必须初始化constint*p=&aJ〃指向常量的指针,指针指向的变量值不能变,指针本身的值可变〃或:constinta=78,b=27,*p=&a;intc=17;a=98:〃出错*p=97;〃出错p=&b;*!尸999;〃出错p=&c;*P=98;〃出错:尽管c不是const的,但是规定p指向的变量值不能变c=98;注意:对于指向常量的指针P,*p不可以作左值2.指针常量定义时,在指针名前加const,标识指针本身是常量,不可以改变指针的指向。但是,指针所指向的变量的值可以改变。例:ttinclude"iostream,h”voidmainO{inta,*constpl=&a,b,*p2=&b;〃为提髙程序可读性,一般不在同一行上进行这样的声明a=100;b=200;cout«*pl«""«*p2«"cout«a«""«b«""«endl;

121*pl=222;//pl=&b;〃出错:不可以改变指向p2=&a;cout«*pl«""«*P2«"cout«a«""«b«""«endl;}/・执行结果:100200100200222222222200*/注意:①定义指针常量时必须初始化,因为指针值不能被改变②对于指针常量p,p不可以作左值2.指向常量的指针常量例:constinta=7;intb;constint*constpl=&a,*constp2=&b;pl=&b!〃出错:pl是指向常量的指针常量*pl=39J〃出错:pl是指向常量的指针常量*P2=39J〃出错:p2是指向常量的指针常量,尽管b不是const常量b=39;p2=&a;〃出错:p2是指向常量的指针常量a=39;〃出错:a是const常量注意:①定义指向常量的指针常量时必须初始化,因为指针值不能被改变②对于指向常量的指针常量p,P不可以作左值,*p也不可以作左值8.6指针与函数1.传递数组的指针数组名是指针,但不是指针变量,所以对数组名不可以进行赋值运算如果把数组名传递给形参,则形参就是一个指针,所以在形参所在的函数内,这个指针可以改变值例:#include*iostream.h*intmax(inta[],intn)//或者:intmax(int*a,intn){intm=0;for(inti=0;im)m=a[i];a=a+3;//okcoutくく・aくく”";returnm;}voidmainO{inta[10]={lll,222,333,444,555,666,777,888,999,0};//a=a+3;//errorcout«max(a,10)«endl;)/・执行结果:444999*/2.使用指针修改函数参数指针变量作函数的参数:地址传递,不是变量的值传递一次函数调用仅返回一个值,如果要在被调用函数的中改变多个值,利用指针作为函数的参数例:每次输入2个数a和b,如果a〈b,则a、b互换并输出程序:

122♦♦include*iostream,hvoidmain(){voidswap(int*,int*);inta,b,*pa=&a,*pb=&b;charc-y,;while(c=>y\\c-Y'){coutくく"、ntn请输入a,b:";cin»a»b;if(a>s;coutくくへn请输入一个被査找的字符:.;cin»c;if((p=strfind(s,c))!=NULL)coutくく"位叠:"くくp-s+lくく"余串:"«p«endl;elsecoutくく"串:"くくsくく"中无字符:"くくcくく"、n";}char*strfind(char*s,charc){char*p=NULL;〃p是局部变量do{if(*s==c){p=s;break;}}while(*(++s)!=‘'〇');returnp;//VC++6.0不警告4.void指针空类型指针:只存放地址,不能进行指针运算,不能进行间接引用例:#include"iostream.h"

123voidmain(){void*p;intx=500,y;charc='?',cc[10]="abcdefgh";p=&x;〃y二・P;//error:不能进行间接引用y=*(int*)p:〃强制进行类型转换cout«y«endl;//cout«*p«endl;//error:不能进行间接引用cout«(*(char*)p)«endl;p=cc;cout«(*(char*)p)«endl;//cout«(*(p+l))«endl;//2个error:不能进行指针运算,不能进行间接引用//cout«(*(char*)(p+l))«endl;//error:不能进行指针运算}/・执行结果:500?8.7字符指针C++语言中:字符指针、字符数组、字符串常量一起构成C++语言中灵活的字符串处理的基本功能对字符串处理:C++编译程序安排一静态存储区域,并自动给字符串未加へ0,,实际所占空间比串的实际长度大1字符串指针:字符串的首地址指向字符串的指针变量:用变量表示所指向的字符串的地址1.字符数组和字符串常量字符串:字符数组,字符串常量:字符串以'\0’结束字符数组:是变量,每个元素存放ー个字符字符串常量:用双引号括起的字符串,其类型:char*例如:chara[10]="123456789";//a是字符数组,"123456789”是字符串、但不是字符串常量cout«"123456789"«endl;〃"123456789"是字符串常量cout«a«endl;2.字符串常量的格式和特点字符串常量存放在数据区的"常量段"中例:与p/168粧例题结果セ同(环境:VC++6.0)#includeiostream,hvoidmain(){char*pl="abcd",*p2="abed";〃如果・p2="abcdef"t则结果是:noequalif(pl=p2)〃cout«"equal

124";elsecout«"noequal

125";if("join"="join")〃如果"join"=="joinn",则结果是:noequalcout«"equal

126";elsecout«"noequal'

127";charal[10]="12345”,a2[10]ソ12345”;if(al=a2)cout«"equal

128";elsecout«"noequal

129";)/・执行结果:equalequalnoequal*/

1301.字符指针例:char*p,*cp="ShangHai”;/・指向字符串常量的首地址・/p="Iamastudent.";所以:*cp表示字符串的首字符*(cp+i)表示字符串的第i个字符凡是形参是字符数组或字符指针,均可以用字符串的指针作实参,进行地址传递,只是注意下标不要越界例:^include*iostream,h*voidmainO{char*p2="abed";cout«*p2«""«*(p2+2)«""«p2«endl;"/执行结果:acabed2.有关处理字符串的函数的介绍包含在“string5"头文件中①字符串连接函数:strcat(字符数组名1,字符数组名2)作用:把字符数组2接在字符数组1的后面,然后赋值给字符数组1;该函数被调用结束,返回字符数组1的地址说明:数组1的长度要足够大,如果长度不够,可以执行,但运算结果出错原来数组1后面的へ〇,自动取消,在连接后的字符串后自动加へ0,(如果长度够的话)②字符串拷贝函数:strepy(字符数组1,字符数组2或字符串常量)作用:把字符数组2或字符串常量拷贝至字符数组1中例:strepy(al,a2);strepy(a,"asdfdfhjdskhg");注意:字符串不能直接进行赋值,例如:chara[10],b[10]={“123456789”};a=b;X数组1的长度必须>=数组2或字符串常量的长度拷贝时,连同字符串结束符一起拷贝至字符串数组1中例:#inelude"stdio.h"#include*string.h"voidmain(){chara[10]={,abcdefghi*},b[5];printf(,a:%s

131b:%s

132*,a,b);/*这时的数组b没有赋过值*/strepy(b,a);printf("a:%s

133b:%sl=%d

134*,a,b,strlen(b));printf(*b[4]=%cb[5]=%cb[8]=%c

135*,b[4],b[5],b[8]);getchar();}/・先执行该程序,然后把数组b的长度改成10,再执行,比较有何区别・/③字符串比较函数:stremp(字符串常量1或字符数组名1,字符串常量2或字符数组名2)作用:对两个字符串进行比较,然后返回比较结果:返回0两串相等>0的整数串1>串2<0的整数串1〈串2说明:•从第。个元素起,逐个往后进行比较,自首次出现不同的字符就比较该字符的大小,后面的字符不予比较(不必长度一定要大)例:“abcde"和“ac",串“ac”大•比较两个串的大小,只能用函数进行,不能:串1=串2④求字符串长度的函数:strlen(字符数组名或字符串常量)例:strlen(a);strlen(ugfhfjgjfgjdfg^^):说明:长度不包括字符串结束标志:へ。,⑤大小写转换函数:strlwr(字符数组名或字符串常量):大写ー小写

136strupr(字符数组名或字符串常量):小写一大写说明:串中的非字母字符不转换注意:不同的系统所提供的库函数的函数名和功能有所不同!因为库函数本身不是C++的组成部分。5.字符串赋值例:#include*iostream.h*voidmain(){char*p2="abed”,a[10]="7890”;cout«*p2«""«*(p2+2)«""«p2«endl;cout«*a«""«*(a+2)«""«a«endl;p2="1234";/Z可以cout«*p2«""«*(p2+2)«""«p2«endl;//a="jkliu";//error:不可以}/・执行结果:acabed797890131234*/注意:字符数组只能通过字符串拷贝函数进行变值8.8指针数组指针数组:是变量,是用指向同一数据类型的指针组成的数组变量即:数组中的每个元素都是指针变量,且都是指向同一数据类型的指针1.定义指针数组定义:类型标识符・数组名[整型常量表达式];例:int*a[10];有10个元素a[0]〜a[9],每个元素都是整型指针变量char*c[100];有!00个元素c[0]~c[99],每个元素都是字符型指针变量注意:int(*a)[10];是二维数组的指针说明:①每个元素都是指针变量②a是指针数组的名,不能对a进行增量运算a是a[〇]的地址,a+i是a[i]的地址♦a*(a+i)分别表示:a[〇]和a[i]的值③用途:主要用于处理长度不一的字符串用二维数组处理长度不一的正文效率低,而指针数组由于每个元素都是指针变量,所以通过地址来操作正文行就很方便④指针数组的每个元素只能存放地址例:char*a[3]={*llllir,*22222222*,*33333*}:〃a是指针数组2.指针数组与二维数组的区别字符指针数组:每个元素是一个指针,每个指针所指向的字符串长度可以不等二维字符数组:每一行所包含的字符个数相同3.指向指针的指针即:指向指针的指针变量格式:类型・・指针名;例如:intx,*p=&x,**pl=&p;即:定义变量P是一个指向整型变量的指针,定义pl是ー个指向“整型变量的指针”的指针也就是:p!中存放的是整型指针P的地址,而P中存放的是整型变量的地址

137例:#include*iostream,h*voidmain(inti,char*s[]){intx=12345,*p=&x,**pl=&p;coutくくxくく""«*p«""«**pl«endl;;}/・执行结果:123451234512345*/2.NULL指针NULL指针:空指针,即ー个没有“指向”的指针,也即没有初始值的指针void・指针:无类型指针例:void*pl;〃pl是无类型的指针int*p2=NULL;〃p2是有类型的空指针3.9命令行参数1.命令行参数如果可执行文件(命令行)需要带参数时(即:程序需要接受命令行参数),可以把主函数定义成:voidmain(intargc,char*argvロ)//argumentcount,argumentvector{......)其中:argc命令行参数的数目,包括命令本身argv指向参数的字符指针数组例:回打参数程序:#include"iostream.h"voidmain(intnum,char*sロ){intj;for(j=l;j

138例:int(*pf)();pf为指向返回整型值的函数的指针1.函数指针的内在区别省略()的函数是地址:max()是函数,max是函数max()的地址函数指针的类型:是函数的返回值的类型函数指针的类型与同类型的数据指针不能相互指向,也不能进行显式类型转换3,通过函数指针调用函数例:#include"iostream.h"voidffl(inta,intb){cout«(a*a+b*b)«endl;}voidff2(inta,intb){cout«(a*a)«endl;}voidmain(){void(*p)(int,int);/*定义指针p是指向有两个整型参数、无返回值的函数的指针・/P=ffl;P(2,5);(*p)(2,5);P=ff2;P(2,5);(*p)(2,5);)/・执行结果:292944*/4.用typedef简化函数指针例:typedefint(*FunP)(int,int);〃声明FunP是整型类型、且有2个整型参数的函数的指针FunPfp;例:把上面的程序改成如下,执行结果相同:typedefvoid(*FunP)(int,int);〃声明FunP是整型类型、且有2个整型参数的函数的指针#includeiostream,h”voidffl(inta,intb){cout«(a*a+b*b)«endl;}voidff2(inta,intb){cout«(a*a)«endl;}voidmainO{FunPp;p=ffl;P(2,5);(*p)(2,5);P=ff2;P(2,5);(*p)(2,5);}/・执行结果:292944*/

1395.函数指针作函数参数例:对任意输入的两个数:或输出大的数,或输出小的数,或输出两个数的和(取决于命令行的参数)的程序如下。♦♦include*iostream.hvoidff(inta,intb,int(*p)(int,int))/・定义指针p是指向有两个整型参数、返回整型值的函数的指针・/{intx;x=(*p)(a,b);/・或:x=p(a,b);*/cout«x«endl;)voidmain(inti,char*s[]){inta,b,min(int,int),max(int,int),sum(int,int);if(i!=2)coutくく”命令行的参数输入出错!

140”;'{coutくく”请输入两个整数:”;cin»a»b;if(*s[l]=,T)ff(a,b,max);elseif(*s[l]='2')ff(a,b,min);elseff(a,b,sum);})intmin(inta,intb){return(a>b?b:a);}intmax(inta,intb){return(a>b?a:b);}intsum(inta,intb){return(a+b);}/*如果该程序的可执行文件名为:cgy.exe贝リ:执行时输入:>cgy1Z就调用max()函数执行时输入:>cgy2Z就调用min()函数执行时输入:>cgy3Z就调用sum()函数・/6.函数指针数组P/181例题7,返回函数指针的函数即:函数的返回值是ー个指针(是ー个地址)函数说明格式:函数指针类型说明・函数名(参数列表)P/1819引用p/185C++中有2种间接访问变量的途径:指针、引用

1419.1引用的概念引用:给对象起“别名’只能对”左值表达式”进行引用引用运算符:&9.2引用的声明和使用1.1明语法:被引用对象的类型标识符&引用标识符=左值表达式例:inti,a[100];int也ii=i,&aa=a[10];〃ii是变量i的“引用”,aa是数组元素a口0]的"引用”1.2用操作使用ー个对象的引用,如同使用其“真名”例:Sinclude"iostream,h”voidmain(){intx=100;int&xx=x,y=999,&yy=y;〃为提髙程序可读性,一般不在同一行上进行这样的声明,应分行进行cout«x«""«xx«endl;cout«y«""«yy«endl;)/・执行结果:100100999999*/1.3什么可以被引用对于除void外的类型T,如果ー个变量被声明为T&时,则这个变量必须能够用T类型的ー个变量的值,或者能够用ー个可以转换成T类型的对象进行初始化。符合上述条件的对象,都可以声明引用(即:可以起一个或多个别名)p/188:constdouble&rr=lJ〃合法,(在VC++6.0中,double&rr=l;非法)指针也是变量,可以对指针变量进行引用:例:^include"iostream,h”voidmainO{inta=12345,*p=&a,*&pp=p;cout«a«""«*p«""«*ppく〈endl;}/・执行结果:123451234512345*/注意:①有空指针,无空引用。所以对void型指针引用非法(void仅仅在语法上相当于ー个类型)②数组名本身不是一个变量的标识符,所以不能对数组名进行引用③T&是类型T的引用,T&本身不是ー种数据类型,所以不能对“引用”进行引用,也不可以有引用的指针④引用是对变量的引用,而不是对类型的引用

1421.1用引用传递函数参数即:用引用作函数的参数例:#include"iostream.h"voidswap(int&x,int&y){intj;j=x;x=y;y=j;)voidmainO{inta=12345,b=54321;cout«a«""«b«endl;swap(a,b);cout«a«""«b«endl;)/・执行结果:12345543215432112345*/优点:起到指针的作用,但并不建立参数的拷贝注意:实参必须是“左值表达式”,例如实参不可以:a+5引用所存在的问题:p/1911.2返回多个值由于引用是“别名”,实参与形参之间不是值传递,而是ー种“映射”,所以对形参的改变,实际上就是对实参的改变。1.3用引用返回值即:对函数的返回值进行引用p/193的例题分ジ:#include"iostream,h"floattemp;floatfnl(floatr){temp=r*r*3.14;returntemp;}float&fn2(floatr){temp=r*r*3.14;returntemp;}voidmainO{floata=fnl(5.0);//float&b=fnl(5.0);//error:函数fn!的返回类型是float,不是float&floatc=fn2(5.0);float&d=fn2(5.0);coutくくaくく""«c«""«d«endl;レ・执行结果:78.578.578.5*/如果把变建temp设置”局部的:^includeiostream,h"//floattemp;floatfnl(floatr){floattemp;temp=r*r*3.14;returntemp;}float&fn2(floatr){floattemp;temp=r*r*3.14;returntemp;//wrning:返回一个局部变量的地址)

143voidmainO{floata=fnl(5.0);//float&b=fnl(5.0);//error:float与float&之间的类型不能转换floatc=fn2(5.0);float&d=fn2(5.0);〃危险:d引用到ー个局部变量上cout«a«""«c«""«d«endl;レ・执行结果:78.578.578.5*/9.y函数调用作为左值例:#include"iostream.h"int&fn(intindex,inta[]){int&r=a[index];〃如果:intr=a[index];则下一句警告:返回一个局部变量的地址returnr;〃返回:a[index])voidmainO{inta[]={l,3,5,7,9};cout«(fn(2,a)=55)«Mu«a[2]«endlJ〃输出:右f左cout«a[2]«endl;)/・执行结果:55555*/说明:函数fn()的返回值是ー个引用,即引用到变量r上;而r是a[index]的引用,所以实际上函数的返回值“引用”到变量a[index]上。所以,函数调用fn()可以作为左值表达式。注意:①并不是所有的函数返回值都可以被引用的,例如:int&fn(intindex,inta[]){intr=a[index];returnr;//返回:a[index])这里的r不是a[index]的引用,r并不与一个本函数外的某个对象有联系,所以当本函数结束时就释放r,返回r并不能起到"引用”的作用(编译时警告:返回一个局部变量的地址。留下潜险)②引用返回值的目的:对函数的返回值进行赋值,作为ー种程序设计的技巧9.8用const限定引用问题的提出:调用函数时,要建立实参的副本(把实参拷贝给形参),如果被传递的数据类型很大,开销也很大,不可取。如果采用指针或引用的形式,则可以不建立副本,但是会产生实参被修改的危险(如果不希望实参被修改的话)。所以,如果调用函数时不建立副本以提高运行效率,又不希望有实参被改动的危险,则采用传递const指针或const引用(即:实参是地址或引用,形参定义成const型的指针或引用)的方法。P/198的例题讲解说明:例:ttinclude"iostream,h”voidmainO{constdouble&a=l;//constdoubleconst&a=l;将警告cout«a«endl;}/・执行结果:1*/由于“引用“a本身不能被重新赋值,所以“引用”总是const的,因此不必对引用a再用关键字const加以限定9.9返回堆中变量的引用“引用”本身不是指针,也不能作指针,所以不能直接对“堆”进行引用。例:int&p=newint(2);〃非法

144合法:#includeiostream.hvoidmain(){int*p=newint(202),&pp二・p;cout«pp«endl;delete&pp;〃或者:deletep;释放堆空间}/・执行结果:202*/10结构10.1结构1.结构的基本概念数据类型:基本类型、指针类型、构造类型构造类型:数组、结构体、共用体前面介绍的数据都是只包含ー种类型信息,数组是构造类型,但是只能存放同一种类型的数据

145结构体、共用体可以把不同类型的数据对象组织在ー起,而形成一种新的类型的变量,这种变量属于构造类型,由用户自己进行构造,以处理一些复杂的数据例如,对于学生,每个学生都有:学号、姓名、性別、年龄、出生日期、班级、宿舍信息;这些信息各属于不同的数据类型,不能用数组对N个学生的信息进行处理;希望ー个学生的信息组成一条记录,N个学生N条记录,便于管理和处理利用结构体和共用体实现结构体与共用体的区别:结构体:内存所占长度为各成员所占内存长度之和即:各个成员占有自己的内存单元共用体:内存所占长度为成员中最长的成员的长度即:各个成员共用内存单元1.定义结构类型和结构变量必须先定义结构体类型,然后オ可以定义该类型的变量(1)定义结构类型一般格式:struct结构名{结构体成员1定义;结构体成员2定义;结构体成员n定义;};例:通讯录:姓名字符串地址字符串或者:structaddress{charname[10];charadd[30];unsignedlongtel;unsignedlongpost_code;);电话无符号长整型邮政编码ー无符号长整型定义:structaddress{char*name;char*add;unsignedlongtel;unsignedlongpost_code:};即:用户自己定义了一个新的类型:address类型,该类型属于结构体的数据结构注意:定义一个结构仅仅声明了一个新的数据类型,系统对结构类型不分配内存(2)结构变量的定义一旦定义了结构类型,就可以定义该类型的变量结构变量形式1:先定义结构类型,再定义结构变量例:structaddress{char*name;char*add;unsignedlongtel;unsignedlongpost_code;);structaddressaddl,add2;形式2:定义结构类型的同时,定义结构变量例:structaddress{char*name;char*add;unsignedlongtel;

146unsignedlongpost_code;}addl,add2;方法3:直接定义,但无结构类型名,只有结构变量名(无名结构)例:struct{char*name;char*add;unsignedlongtel;unsignedlongpost_code;}addl,add2;说明:①用户定义了一个数据类型:structaddress可以理解为:在int,char,float等类型外,又增加了一种数据类型②address是ー个struct的类型,而不是变量名!不能对address进行赋值等运算,而只能用来定义该类型的变量!③对address类型不分配空间,只对其变量分配空间④结构中的某一成员可以又是另一个结构类型的变量⑤某一成员的名可以与结构外的其它变量同名@可以嵌套定义结构类型,但是在某个结构中定义的结构类型只在该结构中有效1.访问结构成员(1)结构体成员运算符:.优先级:最髙结合性:左f右(2)结构体变量的成员例:addl.nameaddl.teladd2.naeadd2.post__code(3)引用结构体成员与单个变量一样,可以进行各种合法的运算、赋值等操作,但是必须指出其所属的变量名例如:add1.post_code=200030;例:structdate{intmonth;intday;intyear;};structstudent{intnumber;charname[10];charsex;intage;structdatebrithday;charadd[30];Jstudentl,s99[101];student1.number=12345;student1.brithday.day=29;

147student1.brithday.month=7;student1.brithday.year=1980;s99[0].number=l;s99[7].brithday.day=5;student1.brithday.year++;studentl=s99[77];1.结构初始化和赋值(1)初始化在定义结构体变量的同时赋初值,不能在结构体类型的定义中赋初值例:#include"stdio・h”structstudent{intnumber;charname[10];charsex;intage;structdate{intyear,month,day;}brithday;〃内嵌定义另ー个结构类型和对象charadd[30];}student1:{9801,"余雨",'m',18,1980,12,1,“华山路1954号”};〃初始化或者:structstudentstudentl:{9801,"余雨",'m',18,1980,12,1,"华山路1954号(2)赋值由于结构大小确定、成员次序固定,所以,可以把一个结构体变量直接赋值给另ー个同类型的结构体变量上例中的:studentl=s99[77];10.2结构与指针指向结构体变量的起始地址结构体变量在内存中的存放:按各成员在结构体类型定义中的次序,顺序存放1.结构体变量的指针的定义structstudentstudentl,student2,*p=&studentl;2.指向结构体成员的运算符:一〉优先级:与运算符“•”同舛厶性,左一右当ー个指针P定义为某个结构体类型的指针后,该指针可以指向任何同类型的变量;并且可以通过指针间接访问成员访问结构体的成员:直接访问:student1.name间接访问:p=&studentl;pー〉name(*p);表示P所指向的那个结构体变量注意:括号不能少

148例如:如果p=&student1;贝リ:student1.nameヽ(*p).name,等价:表示结构体变量student!的成员name的值p->nameJ注意:①结构体变量的指针用于指向整个变量,不能指向某个成员:p=&studentl.age;义②对于单个结构体变量的指针P:P++和p=p+lp—均无意义③++p->age;等同于++(p->age);即年龄加1(++p)->age:无意义p->age++;等同于(p->age)++;10.3结构与数组上面例题中的变量s99[101]就是ー个有!01个student结构体类型的元素的数组例:#includeiostream,h*#defineN3voidmainO{floath_cl=0,h_c2=0,h_c3=0,h_p=0;intnum_cl,num_c2,num_c3,num_p;structstudent{intnum;/・学号・/charname[10];/・姓名・/floatcl,c2,c3,p;/*3门课程及其平均成绩・/}s[N];/・定义N个同学的结构体数组・/coutくく”请依次输入各个同学的学号,姓名,3门课程的成绩(用空格分隔):'n";for(inti=0;i

149各个同学的平均分统计如下:

150";for(i=0;ih_cl){h_cl=s[i].cl;num_cl=i;}if(s[i].c2>h_c2){h_c2=s[i].c2;num_c2=i;}if(s[i].c3>h_c3){h_c3=s[i].c3;num_c3=i;}if(s[i].p>h_p){h_p=s[i].p;num_p=i;}}coutくく"、n课程cl最高分的同学信息:

151";cout«s[num_cl].num«""«s[num_cl].name«""«s[num_cl].cl«""«s[num_cl].c2«""«\s[num_cl].c3«"平均分:"«s[num_cl].p«endl;coutくく"

152课后c2最高分的同学信息:'n";cout«s[num_c2].num«""«s[num_c2].name«""«s[num_c2].cl«""«s[num_c2].c2«""«\s[num_c2].c3«"平均分:"«s[num_c2].p«endl;coutくく"

153课程c3最高分的同学信息:'n";cout«s[num_c3].num«""«s[num_c3].name«""«s[num_c3].cl«""«s[num_c3].c2«""«\s[num_c3].c3«"平均分:"«s[num_c3].p«endl;coutくく"'n3门课程平均最高分的同学信息:

154";cout«s[num_p].num«""«s[num__p].name«""«s[num_p].cl«""«s[num_p].c2«""«\s[num_p].c3«"平均分:"«s[num_p].p«endl;

15510.3传递结构参数即:把结构遍历作为实参传递给形参如果形参是实参的"引用”,则实参与形参之间不进行"拷贝"p/212-214例题讲解10.4返回结构ー个函数的返回值可以是ー个结构变量,如果返回的是结构的"引用"或是结构指针,则注意被返回的结构变量不能是局部变量。p/214〜21710.5链表结构链表:由n个数据成员组成,每个成员看作是链的ー个结点每个成员都是同一类型的数据,可以是任何合法的类型之ー每个结点的信息除数据之外,还包含“下ー个结点”的地址一个“链头指针”:存放链的起始地址链的最后ー个结点的“下ー个结点”的地址为“NULL”:表示链结束

156ー个“链尾指针”:存放链的最后ー个结点的地址(便于appendー个结点)单向链表双向链表:再增加一个信息:'‘上一个结点”的地址(便于删除ー个结点)所以:链表的成员的数据类型是ー个结构体,该结构体类型的成员之一必定是指向该结构体的指针例如:structstudent{intnum;charname[10];floatcl,c2,c3,p;structstudent*p_next;);10.3创建与遍历链表1.建立链表新建链表的过程:链头指针:ph=0链尾指针:pe=0然后在链表中加入结点(append):1.分配内存单元,地址P;成功执行步骤2,否则输出出错信息后执行步骤42.是空链?是空链:头指针ph=p,否则原尾指针pe的下一个成员地址是p3.p是链尾:p->next=0,pe=p4.结束5.遍历与输出链表p=分配ー个内存单元的首地址p!=0?I+内存分配失败ph二〇?I+ph=ppe.next=pp->next=Ope二pI<—结束P=ph~>P!=0?rI+I输出:*ph结束—p=p->next输出链表的过程:链头指针:ph链尾指针:pe1.P=ph,执行22.p=0?(是空链?),是执行4;否则执行33.输出:*p,p=p->next,重复步骤24.结束10.8删除链表节点删除结点:P:当前节点指针,p0:前ー节点指针1.Ph=O?(空链?),是输出“空链”,执行8:否则尸ph,执行22.输入被删除结点的信息3.p->成员值=输入信息?,是执行5,否则执行4ph二〇?1I-Ip=ph“空链”Ix二输入被删除结点信息>IPー》成员值二X?I-pO=pp=p->nextp=0?シ找不到被删除结点p=ph?I+ph=p-〉nextpO->next=p->nextfree(p)

1574.pO=p,p=p->next,p=0?(链结束?),是输出“找不到被删除结点”,然后执行8,否则重复步骤35.删除该节点:p=ph?(链首结点),是,phア)ー>next,然后执行7;否则执行66.pO->next=p->next7.释放p所指向的内存单元8.结束10.9插入链表节点插入结点:1.Ph=O?(空链?),调用“添加结点函数”(append。),调用毕执行9,否则p=ph,pO=ph(p0=插入的定位结点的前ー个结点的地址),执行22.输入插入点信息3.p->成员值=输入信息?,是执行5,否则执行44.pO=p,p=p->next,p=0?(链结束?),是输出“找不到插入结点”,然后执行8,否则重复步骤35.pp=新分配内存单元的地址,pp!=O?(分配成功?),是输出“分配失败”,然后执行8,否则执行66.p=ph?(链首结点),是ph=pp,pp->next=p,然后执行8;否则执行77.pO->next=pp,pp->next二p8.结束10.10结构应用ph=O?pO=p=phx二输入寻找信息IPー〉成员值二x?—pO=Pp二p-〉nextp=0?I+找不到插入结点(pp=malloc())1+p=ph?1+ph二pppp->next=p调用“添加函数”分配失败pO->next=pppp->next=p定义:Np:数组的当前下标num:1,2,3记数number:被删除出去的结点数开始I赋初值:num=number二〇,p二1数组a[l]=l,a[2]=2,...,a[N]=NInumber<(N-1)?Josephus问题p/226-228N个人排成一圈,从编号为1的人开始数1、2、3,数到3的人被开除出圈,再不断地数,直至剩下ー个人,问编号为几?方法1:用数组(7.7节中的方法)#includeiostream.httdefineN7voidmainO{intnum=0,p=l,a[N+l],i,number=0;for(i=0;i<=N;++i)a[p]!=0?I+num=num+lnum=3?&&a[pj!=0?I+a[p]=0num=0number=number+lp=p+lp>N?1+p=l输出a[i]!=0的元素的值

158a[i]=i;while(numberN)P=l;}for(i=l;i<=N;++i){if(a[i]!=O){coutくく”最后ー个获胜者的编号是:"«i«endl;break;}))方法2:用结构^include"iostream.h"structJosephus{intordinal;Josephus*next;};voidmain(){intnumber,num,n=0;Josephus*ph,*pl,*pr,*pdel;coutくく〃请输入总小孩数、数小孩的间隔数(用空格分隔):“;cin»number»num;ph=pl=new(Josephus);ph->ordinal=l;〃创建第一个节点,并初始化for(inti=2;i<=number;++i)〃创建第2〜第number个节点、初始化{pr=new(Josephus);pr->ordinal=i;pl->next=pr;pl=pr;}pr->next=ph;〃扁成一个"诉"pl=pr=ph;while(pr->next!=pr)〃如果pr->next!=pr:只剩ー个节点{++n;if(n==num)〃如果n=num:该节点从环中剔除{pl->next=pr->next;pl二pr->next;pdel=pr;pr=prー〉next;deletepdel;n=0;〃再从头开始数数)else{pl=pr;pr=pr-〉next;}}coutくく"最后ー个获胜者的编号是:"«pr->ordinal«endl;}11类p/232类:是C++程序设计的核心成分,是C++封装的基本单元11.1从结构到类1.从结构到类在C中,结构体不允许有成员函数

159在C++中,结构体允许有成员函数。类与结构体的区别:除关键字不同外(class,struct)的唯一区别是,结构在默认情况下的成员是公共的,而类在默认情况下的成员是私有的。例:ttinclude"iostream,h”voidmainO{structA{intx,y:voidshow(){cout«"x="«x<<"y="«y«endl;});Aa;a.x=3;a.y=9;a.show();}/・执行屆果:x=3y=9*/1.1的构成与定义类可以由成员构成,成员可以是数据成员、或成员函数。成员可以是“私有"(private)的、“公有''(public)的、或“保护"(protected)的。类的定义:class类名标识符{private:protected:public:};私有成员:只允许类本身的其他成员访问,任何本类以外的成员(对象)均不能访问。本类以外的对象只能通过该类的公有成员函数对私有成员进行访问。保护成员:基类私有成员中需提供给派生类访问的那部分的成员,应定义成保护成员公有成员:提供的外部接口,允许类的可使用者访问例:classCircle{private:doublecenter_x,center_y,radius;public:voidmake_circle(doublex,doubley,doubler);voidmake_circle(doublex,doubley,doubler);};说明:①各段次序不要求固定②private、protected、public为访问控制修饰符(关键字),修饰在它们之后列出的成员被程序的其他部分所使用的权限③private段如果放在最前面,关键字private可省,否则不可省;protected、public段不论出现在何处均不可以省④不同类的成员可以同名1.2软件方法的发展必然结构化程序设计►面向对象程序设计结构化:程序=算法+数据结构

160面向对象:程序=对象+对象+对象+...对象=算法+数据结构1.1定义成员函数1.成员函数的命名成员函数命名:类标识符::成员函数标识符::作用域区分符例:Circle::make_circle(doublex,doubley,doubler);即,类Circle的成员函数:make_circle(doublex,doubley,doubler)说明:不同作用域的对象可以同名,在ー个作用域内使用可以使用的同名对象时应加域区分符(::)以区分P/23?的例题说明2.成员函数的定义函数声明函数定义对类的每项操作都是通过成员函数实现的,使用某个操作就发生一次函数调用⑴常规定义即:在类内进行声明(说明),在类外进行定义语法格式:返回类型类名::成员函数名(形参列表))例:voidCircle::make_circle(doublex,doubley,doubler){crnter_x=x;center_y=y;radius=r;⑵内联成员函数定义两种形式:显式、隐式显式:加关键字inline例:#includeiostream,h*classCircle{private:doublecenter_x,center_y,radius;public:inlinevoidmake_circle(doublex,doubley,doubler);inlinevoidshow_circle();};"inlinevoidCircle::make_circle(doublex,doubley,doubler){center_x=x;center_y=y;

161radius=r;!...inlinevoidCircle::show_circle(){coutくく"x="くくcenter_xくく"y="«center_y«"radius=*«radius«endl;}voidmain(){Circlecl,c2;cl.make__circle(1.,5.,7.);c2.make_circle(ll.,55.,77.);cl.show_circle();c2.show_circle();}/・执行结果:x=ly=5radius=7x=lly=55radius=77*/隐式:全部在类内进行定义"例:8include"iostream,h"classCircle{private:doublecenter_x,center_y,radius;public:voidmake_circle(doublex,doubley,doubler){center_x=x;center_y=y;radius=r;voidCircle::show_circle(){cout«"x="«center_x«"y="«center_y«"radius="«radius«endl;});voidmain(){Circlecl,c2;cl.make_circle(l.,5.,7.);c2.make_circle(ll.,55.,77.);cl.show_circle();c2.show_circle();}/・执行结果:x=ly=5radius=7x=lly=55radius=77*/说明:对于开发大型的软件,通常把类的定义和其成员函数的定义分开进行。1.重载成员函数同一个类的成员函数可以重载,方法与非成员函数重载相同不同类的成员函数同名,不是函数重载类的成员函数与非成员函数同名,不是函数重载例:p/239〜24021.4调用成员函数即:成员函数的使用1,类与对象类:是ー种共享机制,提供了同类对象的共同的操作的实现在C++中,把具有相同的内部存储结构和具有相同的ー组操作的对象看成是同一类的

162类与对象的关系:intj,k;〃int是类,j,k是int类的2个对象定义ー个类,并不占数据成员的存储空间;定义了一个类的对象,该对象占有数据成员的存储空间类的成员(数据成员、或成员函数)必须通过类的对象进行访问(只能访问公有成员)类的成员函数必须通过类的对象进行调用⑴对象的定义与结构体类似例:classCircle{private:doublecenter_x,center_y,radius;public:intk;voidmake_circle(doublex,doubley,doubler){center_x=x;center_y=y;radius=r;}voidCircle::show_circle(){coutくく“x="くくcenter_xくく"y="«center_y«"radius=くくradiusくくendl;}}cl,c2,*pc=4cl;或者:Circlecl,c2,*pc=ftcl;(2)访问类的成员操作符:.和・>例:cl.make_circle(l,2,3);pc->make_circle(1,2,3);c2.make_circle(7,8,9);cl.k=999;c2.k=777;2.调用成员函数(1)调用成员函数的方法必须通过具体的对象进行调用P/240例题分析(2)通过指针调用成员函数pc->make_circle(l,2,3);p/241(3)利用“引用”访问成员函数把形参定义成是实参的“引用”p/242例题

163(4)在成员函数中访问成员在成员函数中访问本类的成员,直接使用即可(只要本成员函数中不屏蔽掉类的成员)P/243例题2.this指针this指针是C++实现封装性的一种机制程序运行时,系统自动为每个类提供ー个this指针,一个类的当前对象的地址由该this指针指出,所有对成员的访问都被隐含地加上前缀:this->(p/243的最下面举例)3.类的定义和使用举例例:编写ー个处理学生类的程序,具有输入学生信息、输出学生信息的功能程序:ttinclude"stdio.h"#includeiostream,nclassStudent{private:intnumber,age;charname[10],sex[3];public:voidnew_s(void);〃如果函数没有参数,可以在括号中写voidinlinevoidview_s();};voidStudent::new__s(){cout«endl«*pleaseinput:numbernameagesex:くくendl;cin»number»name»age»sex;)inlinevoidStudent::view_s()

164{cout«*display:“くくendl;cout«"number:"«number«endl;cout«"name:“くくnameくくendl;coutくくage:くくageくくendl;coutくく“sex:"«sex«endK

1651.可见性可见即可用由于允许类型名与非本类的对象同名,所以要访问被屏蔽的对象时,可以:(P/253)1.如果非类型名屏蔽了类型名,在类型名前冠以“class”即可使用被屏蔽了的类型名2.如果类型名屏蔽了非类型名,在非类型名前冠以作用域区分符“::”即可使用被屏蔽了的对象局部类:在每个函数内定义的类作用域:所属函数内注意:①局部类的成员函数必须定义成内联函数,否则违反在函数中不得定义其他函数的规则;如果把成员函数的定义放在该函数外,则这个局部类无法与其联系②局部类不常用名空间:每个名字必须具有唯一的作用域C++规定:①类型不能同名②同一作用域的对象不能同名③类、非类不属于同一名空间,所以类型名可以与其他非类型的对象同名,利用关键字class和作用域区分符(::)可以予以区别2.类的封装将数据与使用这些数据的函数封装在类中,即:数据与操作结合构成不可分割的整体(类的对象)数据和操作可以被保护,使得外界不可访问,只能通过接口访问3.类库的构成C++类库包括类定义、成员函数定义。类定义以头文件方式提供给用户,成员函数定义以编译实现的代码方式提供。4.C++程序结构程序抽象:分析任务、区分不同的功能、抽象出各程序单元模块模块:从编译角度,模块是可以独立编译的程序单元燈r规范说明、定义部分:.h(描述与其他模块的接口)模块!实现部分:.cpp(模块的实现)模块:实现信息隐藏的手段(访问控制:限制类的成员的可访问性;作用域规则:对象的有效域)模块:抽象数据类型的实现工具,也是实现程序模块化的工具

16612构造函数与析构函数类的2个特殊成员函数:构造函数、析构函数12.1类与对象类:抽象的对象:具体的,是类的ー个具体的实例。对象有属性和操作对象的定义:在11.4节中已介绍对象的初始化:构造、并初始化对象12.2构造函数和析构函数由于类的封装性,类的对象的初始化的任务只能由类的成员函数完成:构造函数构造函数:在类定义体中,与类同名的成员函数作用:在创建对象时,由系统自动调用(在编译时,由编译器自动完成),对对象进行初始化析构函数:在类定义体中,与类同名、并在前面冠以“〜”的成员函数作用:释放对象在构造中分配的资源(例如:关闭被构造函数打开的文件,释放动态内存)。在对象生命期结束时,由系统自动调用,并且以与构造函数相反的调用顺序被调用。例:〃配合12.2节(构造函数和析构函数)的讲解例题ァincludeくiostream.h>#includeくstring.h>inti=l;classAbc{chara[10];int*pl,*p2;public:Abe(){coutくく“constructor・・・i二くくiくくendl;strepy(a,"ShangHai");pl=newint;*pl=100+i;p2=newint;*p2=200+i;++i;}〜Abc(){cout«"destructor.,,;coutくく"*pl="くく・plくく"*p2="«*p2«endl;deletepl;deletep2;}voidprint(){cout«"a="«a<<"*pl="«*pl«"*p2="くく・p2くくendl;}};intmainO{Abeal,a2;〃执行构造函数al.print();a2.print();return0J〃执行析构函数

167}/・执行结果:constructor...i=lconstructor...i=2a=ShangHai*pl=101♦p2=201a=ShangHai*pl=102*p2=202destructor...*pl=102*p2=202〃自动调用,析构函数与构造函数的调用次序相反destructor...*pl=101*p2=201*/小结:构造函数、析构函数是2个特殊的成员函数,应严格遵守其功能特性,不要在其中执行其他操作。不要调用它们。构造函数与析构函数的共同点:1.都是特殊的公有成员函数,与类同名;不过析构函数前面加:〜2.没有函数返回值,没有函数返回类型说明但是,在函数内部可以使用return语句,从函数内提前返回(实际上隐含有返回值,此值供系统内部使用)3.由系统自动调用:对象创建时调用构造函数,对象生存期结束前调用析构函数4.不能被继承5.不可取址(即:不可取构造函数和析构函数的地址)6.如果不定义构造函数、析构函数,C++编译系统为每个类自动提供构造函数和析构函数:如果不定义构造函数:系统自动生成一个不带参数的公有构造函数:类名::类名〇{}如果不定义析构函数:系统自动生成一个公有析构函数:类名::、类名(乂}7.一旦定义了构造函数、析构函数,C++编译系统就不再为每个类提供构造函数和析构函数构造函数与析构函数的不同点:1.功能不同:构造函数创建对象,析构函数释放对象创建时所占的资源2.构造函数可以带参数,析构函数不可以带参数3.构造函数可以重载,析构函数不可以重载4.构造函数不可以是虚函数,析构函数可以是虚函数5.有拷贝构造函数,无拷贝析构函数6.析构函数是执行构造函数的逆操作12.3带参数的构造函数不带参数的构造函数对数据成员的初始化,取决于构造函数体中对哪些数据成员进行赋初值,且用此构造函数构造的所有对象的初始值都相同。带参数的构造函数可以使得各对象的数据成员的初始值不同,通过创建对象时将实参传递给构造函数,达到初始化目的。例:〃配合12.3节(带参数的构造函数)的讲解例题#include#includeclassAbc{chara[10];int*pl,*p2;public:Abe(charaa[],int*ppl,int*pp2){strepy(a,aa);pl=ppl;p2=pp2;coutくく"constructor.••”くくaくく""«*pl«""«*p2«endl;}voidprint(){coutくく"a="くくaくく"*pl="«*pl«"*p2=”くく・p2くく

168endl;}};intmainO{intxl二777,yl二999,x2二222,y2二888;Abeal("ShangHai",&xl,&yl),a2("JiaoTong",&x2,&y2);〃执行构造函数al.print();a2.print();return0;〃执行析构函数)/・执行结果:constructor...ShangHai777999constructor...JiaoTong222888a=ShangHai*pl=777*p2=999a=ShangHai*pl=222*p2=888*/12.4重载构造函数即:在ー个类中出现多个构造函数,它们所带的参数个数、参数类型有所不同例:如果在上例的mian()函数中创建对象a3:Abeal("ShangHai",&xl,&yl),a2("JiaoTong",&x2,&y2),a3;就必须重载构造函数:Abc(){strcpy(a,"abedefg");}12.5默认构造函数即:系统自动提供的无参构造函数,该函数只创建对象,其他什么也不做。该函数创建的对象的初始值由对象的存储类型决定(全局的、静态的、局部的)12.6类成员初始化的困惑当ー个类中的某个成员是另ー个类的对象时,如何初始化这个成员?P/278例题讲解例:p/280的例题#includeiostream.h*^include"string,h"classStudentID{public:StudentID(intid=0){value二id;coutくくAssigningstudentid:"«value«endl;}〜StudentID(){cout«"Destrucingid:"«value«endl;}protected:intvalue;);classStudent{public:Student(cheir*pname二noname”,intssID=0){cout«"constructingstudent:"«pname«endl;strnepy(name,pname,sizeof(name));name[sizeof(name)-l]=,、〇';StudentIDid(ssID);〃实际上创建了一个局部对象id)protected:charname[20];

169StudentIDid;};voidmainO{Students("Randy”,9818);}/・执行结果:Assigningstudentid:0〃调用StudentID构造函数创建类成员:id»但用的缺省值:0Constructingstudent:RandyAssigningstudentid:9818Destructingid:9818Destructingid:0*/12.7构造类成员即:初始化类成员1.一般变量的初始化例:intm=10;或者:intm(10);此方式在新版C++中允许注意:赋值表达式中不允许:m(10);只能:m=10;2.类的成员的初始化把12.6节的例题中的Student麥的构造函数改成如下,执行结果就是所要求的:Student(char*pname="noname,intssID=0):id(ssID){cout«"constructingstudent:"«pname«endl;strncpy(name,pname,sizeof(name));name[sizeof(name)-l]=・、〇’;//StudentIDid(ssID);}执行结果:Assigningstudentid:9818Constructingstudent:RandyDestructingid:9818类成员的初始化完全可以利用构造函数完成,在构造函数的原型中利用冒号语法,在冒号后面进行成员初始化:构造函数(参数列表):成员初始化列表例:♦♦include"iostream,h"♦♦include"string,h"classA{intx,y;public:A(intxx=0,intyy=O):x(xx),y(yy){cout«"A...x="«x«"y="«y«endl;}voidview(){cout«"x="«x<<"y="«y;}};classB{intx;Aa;public:B(intxx=0,intax=0,intay=0):x(xx),a(ax,ay){cout«"B...x="くくxくく・A:";a.view();cout«endl;}};ヽ在B类中不能直接访问其他类的私有成员,只能通过接口(A类的公有成员)进行访问voidmainO{Aal,a2(12),a3(l,3);〃或者:Aal,a2=12,a3(l,3);Bbl,b2(789,111,333);)/・执行结菓:A...x=0y=0A...x=12y=0

170A.A.B.A.B..x=ly=3,x=0y=0,x=0A:x=0y=0,x=llly=333.x=789A:x=llly=333*/12.8程序中构造对象的顺序1.局部、静态对象按在程序中定义的次序进行构造(但必须要符合语法)。例:p/258例题:•includeiostream.hvoidmain(){intm=5,n;if(m==5)gotoabc;n=m+l;abc:coutくく"m="くくmくく",n="«n«endl;}/・执行结果:m=5,n=-858993460n是ー个不确定的数・/说明:对于静态对象只被构造一次。P/286例题2a全局对象所有的全局对象都在主函数main()运行前被构造。在单个文件的程序中,全局对象按定义的顺序进行构造。3.类的成员按成员在类中定义的顺序进行构造,而不是按构造函数中的初始化列表中的顺序进行构造。例:p/28713面向对象程序设计面向对象:抽象、分类面向对象程序设计的目的:使用户既不需要懂得太多的计算机、也不需要懂太多的业务。13.1抽象抽象与具体相对应抽象是描述具体实物的必要手段

17113.1分类层层分类细化概念具体化归类:逐步抽象的过程13.2设计和效率时、空面向对象:髙效、可读性、可维护性好13.3讨论Josephus问题p/29313.4Josephus问题的结构化方法的实现按功能划分p/294-29813.5Josephus问题的面向对象方法的实现按对象分割、抽象、归类p/298-306:例题讲解面向对象编程:用户不必了解内部实现的细节,只要了解解决Josephus问题的“接口”即可。面向对象程序设计,编程人员分两类:应用程序设计及编程,类库设计及编程13.6Josephus问题的程序维护P/306;应用程序的功能有所扩展,即:程序维护面向对象:不必改动原有程序,增加类的成员函数的定义;用户更不必关心程序如何改动、14堆与拷贝构造函数“214.1关于堆堆区:动态分配操作符:new动态分配内存delete释放由new分配的动态内存堆内碎块:堆区内众多不连续的内存小块动态分配内存应注意:及时释放内存,避免堆区碎块

17214.1需要new和delete的原因C++:对象建立时应通过构造函数分配空间、构造数据结构、初始化数据。而用mallocO函数分配空间时,不自动调用构造函数;free。函数也不自动调用析构函数。所以,需要增加操作符:new和delete,完成C++规定的操作14.2分配堆对象堆对象的作用域:文件用new分配的对象,在用delete释放前,一直占有堆空间,不管能否访问得到。堆对象创建时(new)自动调用构造函数,释放时(delete)自动调用析构函数分配堆对象:形式1:指针标识符=new类型标识符;形式2:指针标识符=new类型标识符(初始化值);形式3:指针标识符=new类型标识符[数组维数];〃对于数组,不能初始化释放堆对象:形式1;delete指针标识符;形式2:delete口指针标识符;〃释放堆数组例:#includeiostream.hstaticintk;classA{intx,y;public:A(intxx=0,intyy=0):x(xx+k),y(yy+k){k++;coutくく'A'.."くくxくく“"«y«endl;}〜A(){coutくく"〜A.."くくxくく""«y«endl;}voidput(){cout«x«""«y«endl;});voidmainO{int*pl,*p2=newint(789),*p3=newint[10];pl=newint;*pl=123;cout«*pl«""«*p2«endl;A*pal=newA(555,777),*pa2=newA[2];cout«"pal->put():";pal->put();cout«"pa2->put():pa2->put();cout«"(pa2+l)->put():";(pa2+l)->put();deletepal;delete[]pa2;}/・执行结果:123789A...555777A...11A...22pal->put():555777pa2->put():11(pa2+l)->put():22〜A・・555777*/〜A..22“A..11说明:1.动态分配堆数组对象时,不能对数组进行初始化

1732.动态分配堆数组对象时,每维的大小必须指定,不能缺省14.4拷贝构造函数拷贝构造函数:特殊的构造函数作用:当用ー个已存在的对象构造ー个新的对象时,系统不自动调用构造函数、而是自动调用拷贝构造函数;创建新的对象,并把对象的数据成员值拷贝给新的对象(在编译时进行)。拷贝构造函数声明的一般形式:类名(const类名&形参对象名);拷贝构造函数定义的一般形式:类名::类名(const类名&形参对象名)拷贝构造函数被调用的3种情况:1•新建对象:classAし.};voidmain(){Aa;Aal(a);)2.实参传递给形参时:…voidf(Aa){…}voidmainO{Aa;f(a);)3.函数返回时:…Afn(){Aa;returna;)voidmainO{f(fn());}14.5缺省的拷贝构造函数如果不定义拷贝构造函数,系统自动为类提供一个缺省的拷贝构造函数(逐一拷贝数据成员)。一般情况下,不必定义拷贝构造函数。但是,如果构造函数中存在动态分配,则必须定义拷贝构造函数例:开includeくiostream.h>#includeclassA{private:int*p;public:A(inti){p=newint(i);cout«*new...*«endl;}〜A(){coutくく"deletep..."«endl;deletep;});intmainO{Aal(5)J〃调用构造函数Aa2(al);〃调用系统提供的缺省的拷贝构造函数return0;〃调用析构函数两次,ー个值为5的int型对象被删除两次,在运行时会产生问题/・执行结果:new...deletep...deletep...执行到此,出错:指针p已经被释放・/〃定义拷贝构造函数来解决上述问题开includeくiostream.h>#includeclassA{private:int*p;public:A(inti){p=newint(i);coutくく“new・・・くくendl;}

174A(constA&r){p=newint(*r.p);cout«"copy_consructor..."«endl;}~A(){deletep;cout«"deletep..."«endl;};};intmainO{Aal(5)•Aa2(alS;〃调用自定义的拷贝构造函数return0;}/・执行结果:new...copy_constructor...deletep...deletep...♦/14.6浅拷贝与深拷贝浅拷贝:拷贝成员,不拷贝资源深拷贝:拷贝成员,也拷贝资源P/320-322例题讲解如果类对象需要用析构函数来析构资源,必须定义具有析构资源功能的拷贝构造函数14.7临时对象如果一个被调用函数有返回值,系统将产生一个同类型的临时对象来存放该返回值,然后把临时对象拷贝给调用函数,拷贝完毕,临时对象消失。所以,函数的返回值不能是:对临时对象的“引用"。p/323即:对于临时对象,在整个创建它的外部表达式范围内有限,否则无效。14.8无名对象无名对象:实际存在、但没有标识符的对象可以利用构造函数创建无名对象无名对象的3种用法:初始化ー个“引用”、初始化一个对象的定义、函数的实参p/32414.9构造函数用于类型转换利用构造函数,由系统自动进行类型转换。例:#includeくiostream.h>#includeclassA{private:charname[20];public:A(charn[]){strcpy(name,n);cout«*A...”くくendl;}voidviewO{cout«"name:"«name«endl;}};voidfn(Aa){a.view();}voidmainO{chara[20]="Zhangqiushui";fn(a);〃自动利用A类的构造函数把a转换成:A类}

175/・执行结果:A...name:Zhangqiushui*/利用构造函数自动进行类型转换应注意:系统只尝试含有一个参数的构造函数如果存在二义性,系统立即放弃进行类型转换的尝试工作二义性:不能唯一确定被调用的构造函数p/32515静态成员与友元p/320数据共享途径:函数参数传递全局变量具有危害性:破坏程序结构、面向对象的思想静态成员某个类的静态成员:该类的所有对象共同拥有并共享声明格式:static成员声明;静态成员:静态数据成员、静态成员函数1.11静态成员的需要性目的:类的所有成员共享需要性:p/3301.22静态数据成员静态数据成员:在类的定义体中,前面被冠以“static”的数据成员说明:1.如果一个类中说明了静态数据成员,只有在这个类的第一个对象被创建时被初始化,自第二个对象起均不作初始化2.静态数据成员是该类所有对象所共有的ー个数据成员,其值可以被任何ー个对象所改变3.静态数据成员必须在使用前进行初始化,且初始化必须在类的定义体外进行:格式:数据类型类名::静态数据成员名=初值;例:#includeくiostream.h>classA{inta;staticintx;public:l(iatm*O):b(m){く"A…;}staticv»idvi«v()(c»»t«v«s««a41;});iatA:N<90«〉S〃,看IiatA::»900;wiimiaO(Aal,a2;a!F・•0;a2.VM«0;}ハ执行第果IA...SOIA...902金902"9027

17615.3岭态成员的数的态成员函数.在美的定义体中,前圍被冠以".tatic»的成语数员说明,1體倉成员的致不与任何对家联系,不存在tトレ指针2,一般的成g函敏透过tM.指针遂行・用,峥あ成员的数不健通Htli.指针进行璃用.»本成员函敷一般通过类名进行,用I也可以用对旅名限定、迸行苗用,但是甚作用仅是I・过对象名间按埴抬出異房S.在静毒成员函数中,基本上修是访问龄岩数据成员或全局交■,不能对美的非伸合成员送行歌队访向・如果・访阿非»あ敢携成员,利用•数传递进行(以限定0个对象的效指)15.4降态成员的使用M.修车成员函敏、齡布敷製及族初始化*iae1«1•<■tii«.k>claasA{staticiata[20];i*ts;9«hlic:▲(iatx"0)("xx;}staticei&ia();■taticBi&sk();widakAvO{ce«t«*""<)B*«a[i;)vaidnaiaO(A::i»0:〃"用"赤成员函数丁。,初始化伸击敷ttla[20]A::sk()S〃・用“毒成员,散shO,显示静有数aa[2。]Aa;〃定义▲类的对象aへ・卜〇;〃与A::」。同•.•レ・〇;〃显示对・a的敷娟成员值9パ31例H济解15.5需要友元的原因mな仰融的提出,对象的私有成员I只允许本类的成员解斂5网I希載,本美以外的对載或的数的停访网类中的私有成员I友元,熒供了本異外的对象坊向私有成员的・在友元,ー个美的友元可以访问这个美的私有成员(公有成员菖然麓停访问).某个类的友元,肯定不属于这个类的成员.友元可以是ド列2—,友元m敏不属ド任何史的•般メit友元成员另ー个类的茎个成员由数友元美另ー个奏《・个美作友元)注意・友元使华敬掘的射臓性受到・响,&序的可彼护性交差,应慎重使用

17715.5友元的使用1.友元的说明和定义友元声期;ー个类的友元,0般在决类的定义体中的公有段予以直明,并在函数声明前冠以"firi•…友元的定义,发元不属于本关的成员,所以友元的定义不能在本类的定义体中.2,友元语敷友元函数:不属于任何类的、是某个类的友元的一般函敷说明,由チ友元!HK不是该类的成员函数,没有thi.指针,不俭确定当前访何的是事个加拿的成员,所以,友元,依成惊帯有钝道对鉄的,斂,以・定仿M•ヤ对,的数据M;Mxlvd•《エ・・treaa.k>♦iaclvda<0tii».k>cImbA(i&tqア;nblic:iata;A(iatnsO,iattt«OiiatutO):.(□)ジ(ッ)・・(as)0frieaiia(A);frieaivoidsk(A);hBid»(Aal){”—av«t.ア:ci>»al.x»al.r»al.a;c»Bt«aLs«M*«al.y«**«al.a«oadll;)。謎al(Aal)(cot«al,««**«al,y«*\

178友元类的说明:£ri«»4clU.美名:说网,美A和B,B费,明カA的友元獎,則B獎的所有成员丽数■可以访同A类的私有成员例,0iscl>dA<*t4ie.k>*iael>4oelanA(iat・ア;vbMIc:i(i»tnsO,istyylO):s(n),r(yy)0IriradclanB;hcImbB(ckaxa[20);»Mic:B(cUraa[)){■IvcsfUmOs)veilal(Aal)(c®Bt«a«*:*«•1.»«**<d.l;)hveiinaiaO(Aal(lib222);Bbldfrつ;bl.Bk(al);M.Bw(al);”・执行结果,abcdefr:111222ahcdefr:333»/例I»/3Mwa16继承曜承I为一个折的类提供已有类的敷据飴构和镇作憊承是c-的s大・要特性之ー作用,达気町施用性.可ガ克性的目的,建兔&序的重凝&计、重霞开发.16.1继承的概念事獎(父类ル源生新类的类れ生奧(于美),从基奥依生而成的奧基类和谩生类:构成类的层次关系革・承t从ー个基类農生而成的类多嫌承,从歩个基类派生而成的类解承美別:公有辭承、私有軍承、保护解承访问控制।决定子类对父类的访问权限継承类别与访问控制:访问拉制——vAlic公有健承M>wt(私有建承(17.•节17.6节tWB/m)M«t«ct«A保ザ(繼承(17.1节!7.»サI>/»9i/m)・干鏈承的说明t1.如果ア美僂承了父类,勖于奥自动只冇父类的全部敷据成员(敷据皓胸)和成员献敝《功健》:但是,子美对父类的成员的访问有所限制:父类的私有成姑只能被父类自己的成必函敏、友元访问,任何子美均不能え接访问:于类对父类的公有成员的访问权限取决于燃承时的"访忖控融”的设定

1792,于昊可以定义H己的成员,斂据成员加成员时斂S.基类、派生类,父类、子类都是,相对”的16.2继承的工作方式1.派生类的定义弟法Ici“•澈生类名:切軻整加基类名《…•••坊H即個IAv«Mic.®,r・»•ct,42一,软臂力।xie”2.塩承方式0)公有健或碁美的公有段成员被儀承为公有的若美的保护段成员被雄承为保护的派生时用"xMic・作伪时抑制②私有軍旗(17.S1»:»/391)基类的公有股成员被缜承为私有的若異的保妒段成员被鎌款为私有的派生时用"sriwt.*作访问控制⑶保护備承(17.6节,W391)基美的公有段成员被健承为保护的若美的保护段成员被建承为保护的微生时用<><.♦..tu•作坊同控・»/350例•济解16.3派生类的构造例:〃配合16.3刊(・承»/352:渥生类的构遗)的讲解例・^iAclwdc*ixK*trix»class>ee>l<〃人类(レ“ハ・』;〃身份・号(假&i•”型,其长度,r)dkK-[20],*":〃姓名,性別xo,l•(レ“BwdO,ckax*»=*\0*ckaxss'.'){Bw*eraiwi;■6€“(■»,a),“q;}〃构造函数ex.レ.0(£・・・<《people:awaberS*«XMber;“WBMS^aweCC9ses=*«sex«eadl;});cl。,イユMt:Kblicpe”レ〃学生类,具有茶类pe”レ类的全部数据结构和镇作{i>t,メ》;〃学号public:i>t,ノlass;〃班綴st>4tBt(lo&rb«ck*r*ckax・メ・'.i>t»20>iatscSO):people(m«mus){s^raesa;

180s^lassSsc;}〃构造的数{c"tt«as04ckax*mds.、〇ッ:peopレ&mus){stxcp7(departmeat,Bd);}〃构造函数{ce

181V"aセ〈v■(く*4kz-Vzg•■・くくH;});cImbwrfair:9«lilic・宀,〃工人美,具布基类9e•。b和nkざ的全优依鬲帖种和・作(ckar■■6•■[10];〃岗位Kbllc:wrbar(UB<.eUr,—eUx9*■',:■♦■■・0,cUr•一へ。",eUx・・♦・"、0ワ、{・tTCR(■■“•\•+);)〃构造函敷Wi!』レ・〇dl;•・0:veil!mi.0cewt«*cewb«B*«€•ix««««b41;)(»•91•.(911102,'bjummら’」);,"ノ“・0:atvAeat.(7,1010.”■jbjmm,’」)1001バ12);“,レr.(123456,,・ノmm".'J,1111)"£bc""",、;・,・ノレ・0;t.acレ・t(661001.“tノ・w,’」)199金.“・<£•£"Je一つj♦.tノレ・〇;ノレ・〇;〃公有鎌承的濃生粪対象直粳仿时务昊的公有成员t»レ・〇;〃公有鎌承的減卷类財象宜按仿网号类的基奥的公有成员c«>t«t.d>>artmat««ail5〃直蝮功用圣奥的公有敷据成员)ノ田行帖果1A・.l•:aiMbersSIllOS■■artoノ・ar■***afloat:—1・:awdNrfl7ll010MBefe・ノMB«e*Rv•,レr:■eaber:SJBWftlOOl■jb1u"M2awd»rt12349(■■■)■・・・・■HdSlVI'•acレ,:■saber:MJBWftlllld«>artaeattfacHry-1,:aiabetN6181BMettjMJM■•*R■saber:«ノmb1954e.vr..Bc—«rtaeatBcoi^«ttxpe.»le:awihe*N61001aaaeBtjMJMac*ii■(ノwftl9s4

1826.据生类的对れ的生存期结束时偏用は生・类的析构,敷,在博析构,做錯京之前用,用基类的析利,敷I所以,析相函依的被賀用次序与构造,散相反.16.4继承与蛆合配合(也称・聚集・あ厮的、直タ的对,由已存在的、相対简単的时•能成叩,樊的做押成员是另ー个类的对れ对象:由若干个子对象蛆成索1h-18-的体現,預配件的畑合美健何建,在・在这种类型的对霰时,如何对子対象斑行初始化利用构造函数进行初始化,美名::美名(参數列赛):子对家1(初始值列表),于对徵2(初始值列表),…,子对紋.(初始值外表)16.5多态性多毒性।園向対似泰统中的又一重要横名,3大符性上一•歩う性晶通过,敷重裁京实现的・多套性:当不同的对象收到相网的消息时产生不同的动作(本书的多态性概念:运行时・定调用!•个函敷的能力称为多态性)C++*统支持二肿多态性:岱W多态性编译时的多盘性动裏多を性运行时的多蠢性1.静态多态性通过函斂・假实现函敷重裁的二・方式।在冋ー个类中重衾基类成员在诞生类中的重駅⑴在冋ー美中重赦:同名的成M函敷,根据叁敷等不同,自动ア以区别⑵基类成员在派生类中的・債t▼»idb!»w()〇cl«BBB:gbliA(...public:voidskevO〇voidBk»v(ia«b)0。运mia()BUl:•1.〃调用A类的,レ,。•散,慑作数据是封筆7的M.•ル・0;〃调用B类的・レ・()•敢,慄作数据是对SLH的M.«UV(5S5)i〃调用B类的・レ.(iat口)喻敏.■作斂据是对象M的〃调用▲奥的・レ・

183。•敢,事作数据是对,LH的1.动态多态性C++中,运行时的多套性是通过虚曲数重我来实现的26.6多态的思考方式対ナ同一件事,对れ不同,实际操作冇所不同.例如:学生注册收疑,本科生、研究生所收的费用不同,注历觀章不同»/S57例融36.7多态性如何工作运行时的姿态性通过キ函斂实现虚函数,知一种功击的画数■假的方式,虚函也允许丽敏调用与函数体之间的取系在运行N才・也・1.对叙指针可以透过指针访问对象例:classk{...>«blic:«1••()0•••1.1,y&>;••«p->ヌレ・0:*1.ske«。:•般对象的指针:各类的指针相互独立,不能混用例:classA(...}al,<*■;classB{…}11,**b;指针3只能指向▲类对家,不能指向B类对象:指针通只能指向B类对,L不能指向A类对派生类的对象的指斜:淑生类与基类相互之间既相互独立、又存在壌承与被軍承的关察,所以,希生关的指针与基类的指针之间相互有关.2.为什么引入虚密敷例:tisclwle*iostrcMi.gblic:««id■1•*()(i...*«aadLl;)v»idviavO{c•・攸く〜eluuti▼£•«()...}):cImbA(iat”;“道・レ・()

184(iats;vaid・レ・()*1•,〇;zM>;〃.>・卜。;〃出候,茶獎指針可以指向線歩獎,但不可以通过雑指针访同不履于堅美的成员paBfcc;((>■)«*)*>■%•«();((Bf)*■)•>■!();((C*)*^->«U«();((C«)*^«>il();((C«)m)->▼&••();)/・执行务果,clu・A...claaaA...elaaaA...claaaB...cl«*aBb、〇…cImbC...claaaCbhO...cla*BAview()...•/执行鮎果分析I珞昊的指艸可以指向派生类的対象.但是,■姓指针对成员函敢的偏用,仅仅当抬外本身的美量有关,与指针当的指向的对・无关•如果要り当前对れ冇美,Q須対指针类型进行强制轴铁.I理过指针进行ー料动赤的指向W»指加指向的对我不同,执行不同的重債成员曲敏I引入虚・«h把上例中基类的bレ・()函故期・班・函数即明(メ敷原型的加美•字Ivirtwl)性・,①ー个声・为若奥对・的指忏可以指向它的公有植生关的对・,但是不能指向其私有無生关的对拿②ー个声明为派生奥的指针不用以指向其基类的对氨即ー个声明为基类时象的指针,加果指向它的公有据生类的对象时,只健利用箕米访蚓聖奥的被公有併承的成员,不能防冋軽生奥自己的成员④ー个声明为墓类时象的指针,如果指向它的公有・生类的対象时,明以通过对指W興量进行强個特畏来沙同派生关自己的成员2.虚函数的定义和使用定义!在函数原型前面加“Gr21”即可例h上面的例題,把类A的成员的数・レ・〇改成虚雨敷,其他不作任何改动,▼irtwalT»idskowO(cout«Vlass)然后执行,执行鮎巣如下,clwsC.7Z〃指针pa已經指向。而・レ・〇是虚南敷,O)p^->sk»0;classBsh〇…classC・.・classCsh〇…claasA■£•■()・・・例2,■/SS•例题讲解36.8不恰当的虚函数Mh虐扁斂的摩型。别相同《函数的蛆回奥量不除外),才能实现多有性,否則不管是否冠以•virUal"声明,均作为一般直裁函敷处理,失去废特性.虐椅性可以隔代传道♦iaclwdA♦ixUM.aclassk(iat.ア;F*blic:▼irWalwidskov(iata=0){cewK<*jL:)〃声明カ虚,曲数);classB:9«blic▲

185(>«blic:vir21B建宀,〇(“・t«F:.«.辺!;)〃般的成员曲数・我,不是废曲败重ft1;classC:>wblicB(ywblic:widsレ・(£>・上0)«ce>t«*C:"くGadi;}〃虚歯敷重教);classD:vbM&cC(pwblic:Bidsk»v(iatteO){ce>K:\>w;)〃虚歯敷窟皺);tvidn&iaO(A■,Bb;Cc;Dd;xs>b;"■>宀,〇;〃执行基类▲的,ko・0函数pa=&c;paM>s^»wO;paslbd;pa->sK»«O;)/啪行勘果:1:D:W例箝»/%2例・济解*iacl>d«classBase{ywblic:▼xrtvalBas・・afa()(isntvntkia;)hclassS«¥Class:9BklicBm«(“blic:Bbs,・afa(){ce>K<*TkisisSbKIms.\>*;retmtkxs:)):veiiUst(Bbs«^x)(&m«・1;bto.afaO;vti

186在ー个软件(程序》中,如果类的划分不足合理,便会造成信息成功能憬作的冗余.因カ,这当奥中凤般不同的美,如果善奧中包畲相同或粕近的佶息,这当信息以分离的形式出现ル余.ノ”4例鹿讲・16.11克服冗余带来的问题克厳冗余,令期的承承16.12类的分解分解,从不W的奥申”取并能令共有冷怔的过程.即把善美的共同特征抽取出泵,然后把地当特征放到上面,作为这些美的帯类.目的,M少編程工作量,提髙软件质量.JS71例题16.13抽象类问・的提出:有时基类往往表示一・抽藏的慨金,这片类并没有具体的对紈,其成员由敷也并无具省实际意义的欄作,这片美认为是一种抽象的关・1.纯虚函敷触虔函敷।茶类中的永运不依调用执行的虚函敷称为純虚函数他虚函斂的作用I利用其盧メ敷的仲康依性,达到饉承的动毒多毒性U的触虚函数的定义;Ttnl函數返回美M的数名(•敷列表)ゴ;说明,・峨敏被声明成他盧函敷,就不必班行函敷体定义2.抽象类抽家类,至少包含一个钝虚函数的类栋为抽象类抽裁类不健创建对れ,虺为众多派生类提供共同的数据站构和,作抽欽定义16.14由抽象类兼生具体类“377例履讲解16.15纯虚函数的需要性W37I例題か解关于抽蠶类和触虚函数的说明t1.抽象类只能作为其他类的基类,不能创建対盆.

1871.抽れ奥不能用作由斂層,的美型、賦敷坂回类型,不能造行貝式異型转換.,.可以定义捕魚类的指针,此指针灯以指向其非抽紈类的澱生美的对象,以实现动念多盘性.4•在抽黴美的派生美中,如巣没有蛤出茶美的的虚函数的具体定义,用谀废生美仍是ー个抽象美।M果在漫生类的※生类中,还没有蛤出毫类的饨虚南数的尺体定义,則慎派生美的派生类还是ー个他拿奥・17多重继承多重軍承國多軍承,由多个茶类派生而成新的类17.1多继承如何工作类A、B、C、ル継承鮎构Kh类D儀承类A、B、3类。是类▲、B、C的派生类,类。包含类aB、C的所有敷据成员和数据鮎例:4iaclvd«classA(iati;Kia*ii=0)(i=ii;c»«*«"A...i="«i«eall;}{e・3«Z::宀,〇is"«i«*adl;});classB(ia*i;B(»*iiR)(i=ii;co3«"B...i="«i«*adl;}{e»«t«"B::s^»«0i="«i«»Bdl;});classC:vvblic&v«blicB(iati:public:C(iatil0,iati290giSsO):Kil)»B(i2)(isi3;c«wK<-C...i="«i«*adl;)Bidsk»v()(c»b*«"C::sM,0is"«i«eadl;〃s1。・〇;〃根据ー支配加剣一,调用自己的类的成员函数宀・〇,出现死循环BidRmiaO(C€(1.2,9);C.▲::Sレ・〇;〃调用对象C的筋类▲的成员的敷Sレ・()C.Sレ・。;〃根据”支配短!1T,M用对象C所属的类C的成员函数・レ・〇)ノ哪行帖果:▲…i=lB...iWC...iVA::sk>«()i=lc::sk>«()i=3♦/17.2继承的模糊性模糊性:二义性

188二义性,对某个成员访网不能瞰ー确定二义性产生的原因,不利美的成员可以同名煩定:在霎嫌承、多层次的维承鮎构中,16是逐层往上、访问・靠近自己的那个闻名成员•但是.如果在同一层的两个类中具有同名成员,则产生二义性・

189c1m>AMlic:eidfu()(£・■«く〜A:f«・〇<"));classBl:>«hlxcA(vwblic:eidf«*l(){ca«K<_Bl:f«al0;)hclasaB2:9«hlicA(vablic:eidR»1(){c«wK<*B2:ful0~««U1;)):cl«s.CivablicBl0;classC2:9«blicB20;classD:>«1>1icCl,vablicC20;B谑MdaO(D・M;Z/.kifuioS〃不可以执行:二义性(Bl和BZ是两个不同的类,各有20歯败)•¥j.Bl::f«*l();•bj.B2:fwlO;〃.加.一〇;〃不可以执行,二义性(在B1和B2中都有00虏数的“副本.)〃・句.〃不可以执行‘二义性•hj.Bl::f»O!〃无二义性:可以执行B2:Kb1()”咻行結果:Bl:f«al()A:fuO*/二义性解决办法।①在成员名前用美名进行限史(类名::成员名),可以解决同一层的荫个类中具冇同名成员而产生的二义性②虔基奥(即虚扱蒙承),可以解决上述协问同•个若美的班员、但存在多条路校的句题17.3虚拟继承制,把ヒ记的昊Bl、Bノ改成由A興虎掖般承而成*iaelwhcluaA(»«l>lic:v»idfu()(e«**«**!:fu()*«a»Al;});clu・Bl:“rQ*lflicA(v*Mic:v»idHal()(£•«*«*B1:ful()*««adl;));cImbB2:vi*tvalgblかA(**blic:▼aidfval(){c*«*«*B2:fval()e««adl;)hcImbClHieBl0;cImbC2:»bKcB20;cImbD:>BblicCl,ElieC20;▼•iimia()《D・W

190〃不町以执行I二义性(Bl胤盤是問个不同的美)•kj.Bl::ful〇S•kj.B2::ful();•kj.fwO!〃可以执行I无二文性•kj.A::f«O!〃可以执行I无二义性Z/.ki.Bl::f~()!〃无二式性I可以执行”・行伟果।Bl:f»l()B2:ful()A:00A:f»O*/由收伊承的横念I在多条辭承路押上存在ー个公共的基类,在这枝跡径的汇含处《某个氓生类)就产生这个公共基奥的多个"副本”.如果只希望存在ー个剧本,可以把此公共務类由明为虚あ興《虚扱便承).由网飾承的方法।虚斗奥是対派隹奥而百,所以,由多奥本身的定义不变,在定义雅生奥H声明慎基奥力・基奥如灯(就以关健•“virt«l).17.4多继承的构造顺序即I在多鏈承中创・景生类对れ时,构造函数的訳用順序*>acl*daclaaaWa«l(iatzk;V«klic:ー・Miat30,iNktaO)〃椅抵成斂,是符缺有值的,或者是无,敷的(**»;takk;。•・必ヘ・a・lclMslw««»dl;)v«UbU«()(c»«t«*U8al:■**«»«*kB*<(c««t«*^M«2cleBBl*«aMll;}。建bUvS(){"バ<(X・2:M«aaAl;});c1«bblevalllpvSlicksa・2,▼irtval9*klicka*«l(p«klic:l«Tall(iatziatk):k*a・l&k>cIbbblaval2:p«blick»a・2,vaklickaa«l(v«klic:l«v«12(iBt2iatk):k*aal(«,k)(co«t«*laval2clesaI;}cIbbblastlaval:9«kliclavall,TirtwilF*kliclava12(p«klic:lastlaval(iat.iatk):lavall(a4k)(lava12(a,k)(c««««*lwtlavalclanド《a*Al;)hvaii7ao(lutlaelakj(7,9);•kj.U.()!〃直接调用阿接圣奥k-・的公布成员函敢,“,〇一硬二又住//•kj.•ン・2();〃切H间簾基类k»a2的公布成员函斂,M«2()存在二义性”・行傩果,U>alclo.lkaaa2classIUva12classlkas,2classIl«vallclassIlastlavalclassIWsal:alOWO17.5继承类别及其访问控制公冇成员,ー个类的公有成员允W本类的成员函敏、本类的时今、公有マ生类的成员メ敷、公有駅生类的对魚苗句私有成M;ー个类的私有成员只允许本美的成员函数访问保护成员,具有.私有成员和公有成员的特性,対其れ生獎而吉是公有成员,对其对象而吉是私有成员

191例1,类的保护成员♦ixU…iati;iatj;▼•idakAvl(){c««K<^k»vl():is*«i«*jsv«j««adl;}wblic:A(iats.iaty){i=;j=y;)▼•id・レ«2()(iゴ《キ«"推"<3««dl;sU.10;)〃成员函敷可以访网保护成员);iatmia()^*1()S〃不可以宜接访归类的保护成员:・b»“O•1.aK»«2();”・执行鮎'・"也。:i=73=9•k»vl():ii7j=9•/公有継承,基类的公有段成员被继承为公有的,基类的保妒段成员被卷承为保护的•派生时用•public”作访向控制・私有饒承,務獎的公有段成员被・承为私有的,茶类的保护度成员被・承为私有的,濮生时用•private»作坊W控制・保护・承,碁类的公有段成员被继承为保护的,基类的保护段成员被健承为保护的,派生时用-protected"作访问控制,公力軍承的功向押MM1对基类的公有段成员的协何,尤如切问自己的公有段成员I对基类的保护段成员的访问,尤如访网自己的保护段成员.私有憊承的访向控制;对毫类的公有段成员的访问,尤如访问自己的私有段成员:对M类的保护段成员的访问.え如访阿自己的私有段成员.保妒健承的功付控制|对基奥的公有段成员的5何,尤如け问自己的保护段成员I对基美的保护段成员的访问,尤如访问自己的保护段成员.例2:类的私有雄承*i*cK*tr3classx”le〃人类(レ“,.』;〃身份比号(観设レ”型,其长度幡了)clar*mk[20],・・x;〃姓名,性別V*blic:»«»l*(l«ac>wC0,ckax*b="'〇”,ckars=*m,){stxcs7(»MM,a);sexai;}〃构造函数

192。建』レ・0{«•«<<<;cest«*bmmBw«mimi«*aesft*«••*<riwU»•>!e〃教]:奥・只冇基奥»•奥的全部敏掘结构如愫作(i»*V;〃エ号—私冇成员xblic:cUrdaparbMBt[10]S〃部门ー»公布成员■wafair(lear.ckar*—cWr■・ゴ,i>tanftO,ckvr*mdl*\O^(、4・){ym;BtrcvrtdApaztwiat.Mi);)〃构造函敏b建"レ,〇{<:•■«《•・宀・:•くく・皿マ"・〇:〃坊忖基类的公有成员«•»«<*mjmmS・くく・^^!■<<“viiiiBBK7(■<<<>•»«at):)〃构撼メ数"レ・〇;〃访"站獎的公冇成目€•・«《・■tat1•«**<<«tatieB«esdll;}卜elaa.t.acレ/:>riet・・・レア〃教师奥,AWM^•••>!•和,•・・的全部敷据储种和修作{c,・t《く,宀・:・くく•皿(eレrcowr”[10];//MttURffxhlic:t-レ雪(1.B7(c«WB«/tc);)〃构造メ敷“谑tノレ・(){c,・t«‘t・»cレ,:・くく•adl;ソレ,!);.〃坊忖基类的公冇成员ce«t«•c・3r・•・・くぐ。•u・・《・Bdl;)mUb()(wo,レ/«(1234SS>*vjMos*f4^,1111)“,ア”,ゝ日4つJ■,ソレ・0;■.叫ノレ・〇;〃«•,ト美公布錐承1《ト,.所以即1以直接访蚓nk,类的公有成员〃,ソレ・0;〃—レ,类私有僂承X”1•,所以不可以直様出蚓…ハ・美的公有成员t.acレ,1((61001,*tjBMM*/^1195%つi九t/レ・〇;〃t.・丁レ・0;〃”“レ・奥私有鱗承1人,,所以不イ以直接坊何・宀,奥的公有成员〃t.ソレ・〇;〃”acレ,奧私有辭承me・1,.・・卜雷私有辭承x”l・奥,不可以直接协问)ノ毋行餉果,w•宀丁:・・卜丁:BAMfeVJMBC.e*Rdfixxt—t.fwcN,,aiaberB12945(«ノwftllll■teti«B*iBitk・・卜>,:pee^le:♦•ACレ,:・・卜,:9•>91•:aiaberfl12945(«ノwftlllluaetvノ!MMaevBmdfi^artwBtBfBCHryawiwrHdMl!!ノW1954cowb«Bc44BJMM»BtjBAJM«C*R

193例如奧的保「鎌承♦ixl亠ぐ”iati;>arot«ct«d:iatj;tb14■kftvjLl()(c»bK<():i«*«i«*jB*«j«eB41;}nblic:A(iat,iaty)(ito;jty;}。建・M・/20(・レ!□!】();”“ぐ宀イ0:il*«i«*jB*«j«a»4ll;});cluaB:sr«tect«dAiats;»blic:B(iatLiati,iatk):A(i,j)(d;)▼•idak^vJIO(e・.!<《"《!«.」BO:aS.《cImbA(private:iat*;pretected:iatア;Kblic:iats;A(iatn,iatmiatsa)演(ロ),バ0void*A(){ce>t«*A:»•*«»«**yl*«y<<*■■”《<・ぐく••41;)g建•ll(Aa){ce>t«*>»*«»«*a.sS*«B.v««a41:)eid£A(Aa);hBiUfA(Aa)〃A的友员函数(co*t«*fA():*«a,■«*\c«>K

194cImaBl:publicA(Kblic:mistrftiatu):A(h.77,3)〇voiiaBI(Bl'){//coK4”建SI1(B1¥);6rie>4。运S12(Aa);h。進fBlKBl¥)(〃="《。.Bくく・ヽ0BK<*fBllO:"(。.yくく"c«Bt«b.a««ail;〃※上実的友员不能访蚓第実的私有成员、〃据朱実的友员可以甩过该津生実的对,I仿忖聖実的保十成员〃軽生実的友员可以甩过该派生実的对象び忖堅実的公有成员“建fB12(Aa)(〃“■”く・.»く,*;//«•><«<.y«**;〃津生类的友员不健通过基実的时象仿何基契的私有成员〃濛生実的友员不值通过基実的对象坊向务実的保护戌员e"(ぐ£B120:”«■,・くGail;〃j|生獎的友员可以建封号異的对象皆向基类的公冇成员cImsK2A(Kblic:B2(iatmi"ッJiataa):A(B«yy.Ba)〇wiii・B2(B21)《〃c”tく。くL*;〃不能访问基実的私有成员〃co・K。.a<く.*:e"«Kく.•;“"<。・yt«a«**;

195¢**<<<¥.!<<•>41;A-(41,51,41):〃昊内部创建的岁本奥对蠶不侑仿H基奧的保F«成员〃co3«a*.y<<"";//c*«t«aa.i<A1(>2):M1,bB1(M2);Ml.aK(¥22);¥31.H(¥32);〃c・・t«bll.K<.《il;〃类外部创・的对・不倦び柯學獎的保「成员HUI);fill(¥11):fB12(a2);)/・执行鮪果I"44a."44451139sal«i341228133”41A:。11椎22a*33222M83339”41A:0111t«222a1333fA():445544flllO:23¢012():466<18运算符重载®/3H*«.网名不同义,在不同的情况下可表现出不同的行为.前数重・掾作符重我个运体符可进行,种不同含义的・驛I!作符京©।使种操作将适用于类的对象之同的•作,提髙程序的可设性,18.1运算符重載的需要性问题的类出,在C++中,定义ー个类就产生rー个新的类型,类的对总就和变量一样可以作为,敏进行传通,也可以作为函数的返回类覇I希望某些运)r符能・对・个财家进行掾作,而不是c中的同单掾作,例加:♦运算符能悖实现2个对銖间的加4把某些事交計京统去做,用户只基知道和加紘町I类出运算符重債,扩充运算符的功能.即,对运算符进行■■定义,然后使用,由系统自动内断究竟果用鼻ー个具僮的运年符増强了C++语齐的可犷充性例如,类A的对裁7、«2、2,枯置:7=7+«2;V・分期把时,7和・2的各个敏据成员值对度相加.然后M蛤对象」实现途径:掾作符・段18.2如何重載运算符重装运体符的实现:运算符歯数,即以掾作符命名的函数(重我掾作符)纖作符重價的函敷名施定,由关9字

196%p«r*t.r"和操作符組成例如,类A的时敷一利盟相加,就M用-•p.z.tez+"Aftal-**eraUr4(*ba2)al4*2,-al.«>*r*t«r*(*2)类类型的摄作符兩ft可以是成员函ft或友元函ft・1.一元操作符・载的一般形式⑴重堂为成员函ft(有QL・指针)返回类型标识符。8"ヒ8被・俄的掾作符。;重・定义,建回奧里标以粕类・标收符::.*»a,“被重就的)»作将。{…)②重质为友元函ft(无tkis指针)*«*«:fri.U运図类型标识符。餌..,"被東侵的!・作符(“at类名・形・名),重•(定义,返冋类型标识符・3at”被重我的掾作符(“ast美名&形参名乂…)2.二元操作符■載的一般形式⑴值債为成员函ftdrtu.mit)・税点・,蛆団臭型标以构•Mr.fr被重就的!・作将(“at美名・摩・名)i重教定义,返回类型标识符类名标1A籽:.xrator被重栽的•作符(“at类名"摩•名”…)②重或为友元函ft(无・hi・指针)重・声明,fri.U返冋类量标识符.xator被重我的据作符(“》»t类名・博・名Leas«美名・拶•名2):・假定义,建回奥型梅以料•M»«t.r植重■的!»作将(“ut美名・博,名しc.ut美名・序・名2){>例h二元加、一元减像作符京・为成员的ft*iacl«d.tx.r;wblic:&(iatki>Qrr):s(w)Fy(yy)0A()A(”uQIH){r«tw>A(T».・・kb.yy);)Ae>»rat«r*O(A(—r);){c»>K<*>»*«»«*yt*«7««b41;1);(A.1(X55"<2®66)心〃賀用操作符重裁・敢:7.・xN“♦(•2)aS.flkavO;・1Z1;〃ビ用操作符重假・数:»0•1,•レ・0;)/峨行結果:7*121+5y«-S57

197例2,二元加、一元M操作符重或为友元的數classA{xat.ア;public:A(iataiatyy):s(sk).y(yy)0AOfrieadA,pax■,"♦匕。astAinucoastUb);£rieadAo>exator*(coast11*);toidslowO{eouK<**="«*«*ye*«y««adl;}hAop«zatoz*(coa*tAfai»coastAtt)fretwaA(9.TiwkVア);)Aoperator*(coastAha)fretvaA(fwア)”toidirnuaO(A■10S5"«2(加”),《3;2h10;〃调用,作符重供函數:al.opratoz♦(2)a3.slov();alAal;〃貴用操作符重栽函数:al•paratoM•〇al.slovO;)/M行鮎果:匸11y^lZl>=-5y0-35*有关掾作符重■函数的说明i1.,敷个敷有所規定।ー元纖作符只饅有一个参数,二元掾作符只能有二个参敷;但是成员函数与友元函数的表现摩式不同2,返冋类型可以任恵,但是・好不要定义成Bid,・操作符重鐵函数的功能应明确.一般不要执行其他不相关的掾作.4.・•后的掾作符的使用语法・优先級、鮎合性均不变.5•如巣操作数都是C”的答本数据类ホ,不允许对•作符进行重・6エ»规定】、〇、n、•>这4种纖作符必須重載成成员函数18.3值返回与引用返回注意,不能对髓时对象进行“引用”•如果w数的返冋值是个临时对象.画采用•值返冋,W40I例』18.4运算符重载为成员的数•作符«假为类的成员国数,上网已介的过西科・我形式(成员的数、友元函数)的比较,1.一元後作符・或成成员函敗较好2.二元・作物除=、〇、【】、->这4肿操作符必须重教成成员鹵敏外,其他操作符・我成发元的敷较好例,•是美▲的ー个对,,対于表达式,27.5+,时友元函数不存在问Aし・xrNs*(A(27.5),«)但是,対成员・敷存&M・t(27.S).・xnQ”+U)〃#怏,27.3不是ー个对れ,无thi・指针38.5重載増・运将符++、ーーI是一元•作将但是,可以是谛變或后無.所以,重教时有所不同««|一元欄作符后俶,二元操作符

198例ト++和一操作符・栽成成员的敷Macl*«。…2»classCouter{usimedw.lw;public:Coutex(i>ttsO)Coutex•parat>r**(){elu**;«•<♦«*1,..*<<^b1w»«**;r«tvr>t'tkis;}Cevatez•parator4*(iBt)(Ceutezt;”・・«"2・・・・«elwt<<・♦.wlwsvalwe**;retwat;});toidhhubO(Jut”a(ll)4b(22)»c;,Mb;〃ロ动词.用0ふdi99190;csW+J〃口动调用•xx.t9x-li.t)b.display();-0;)/啪行飴果:1...12122.ハ2223223例箝一和一操作粉・假成友元国數亠くi”t”s.k>classC«ut«x{iMxr**dw*lw;public:CevaUr(iatvsO)H—;)fri・»dCevatex•9”・・”“(C・wat”紛;fxi・>dC«vat«x・xr•“ぎ”(C・vat•ヌムiat);{c»*t«valw«e*41;});Csvater•por*tor4*(C«vat«rlKc)(cc.vbIm**;..*«cc.v*lw«**;x«twacc;}Cavataraperat»r4*(Cevatarfccc,iat)(C«ut«rt;c»«t«"2...•«cc.wb1w«"ヽt.elaBee.elu—;rctvrat;)voidmia()(Covaior.(11),1(22),e;f;〃自动偏用0wirator«*(Covat«ri)a.display0;csW*i〃自动调用•>a*at・M2(C・・at・,*,iat)b.display()jc.display〇5)/•执行储果:1...12122...222318.6类型转换运算符类是用户自定义的类型两个不利的类闿无法进行类型转换,奧昊型转排指,奧"荐本奥量之间的转换类类型转换实际上是通过“重我”实现的类型特快।・犬系统自幼完成帏铁r强!w转换法•亥I加《(H櫟法类的类型特快均HR式、丽敢转换法

1991.基本敷据类型间的转换R式幡换I例,intx;nouり;尸x;〃y=x;ift行(t式幡帙見式转按:①颯制转换I例,Ut«,y;float«(float)M;②函敷转换t例,i>t»y;float.S・=floatQ*y);〃括サ不珑吿2.类类型与基本类型之间的转换・式や快,利用构造南敬完成由其他舗本类型向本类型转换的,作慟果无相成的构造南斂,刚被禁止转换显式將换:利用类型转换的数ーー完成由本美©向其他易本类型转换的操作・明格式,•poato<类型标识将〇;定义格式,类名::oo*at・・类型棹恨得。说明,类獎型特投兩数I无岸敢返回类型,无套数.因为,总是转换成"类双标识符.所指出的类型,R被转快的◎是本奥的ー个对象(由thi,指計ガ出).例;Iiac1wbcImsC»v>t«r{>>t▼1;cWrt2;K、lie:CemUr(iB*tsO.cW▼1*▼;.2e;)ckar()(retvrav2;)iat()(retwa▼1;)voilAia>lay()Tll*«vl«*辺—《,2«・皿)Centerfa(C«uierc):):Center£a(Cevaterc){c.vlBe.vl4Q;retvxac;}widaaiaO(ckaj・;iaty;Center7(64/片レc2(99Jザ);cl.dia>l«y();c2.di>*lay();c2tfa(12345);〃实,12s45量域构域函敷Cente'(・・1“〇,ekrE屮)純換成Center奧型c2.dia>lay();01;〃通过成员・敢•a”“,eLurO特接成型ml;〃通及成员・敷•♦•,iat0特検成iat量ce>t«s«9*«y«e>41;)ノ田行结果:Center:,1M4<2«MCenter:t1K)9,2tlCenter:vlt244)0t2b?V64♦/18.7限值运算符在一般情况下CH・允许同类的两个时今互相・值,例如I«1=«2;〃表示,把对紈«2的各敷捌成员的值逐项复制蛤对象.1但是,在某些情况下会出现问题,例如"指斜悬控"(s/S2L肘&创建时存在动あ分配内存,析何时就会出现指针黑挂)何題,这时。舞对类的・值运算符进行・載,以解决决阿・.另外,如・対れ的某个敢挥是指针指出的不同长度的数蛆时,也需要多處メ值垢算符意載.W4H1例建分析例[*i>clvdep«Mic:A(ckaz«•»){SCMWcUz[atzleabp)*1];

200stxcvy(9ir);ce«t«*>ew…”《くメ(eadl;}〜A(){delete>;ce«t«*deletep...*«e>dl;}Ue>e»terS(Ur);〃院值运算符京載成必函倣);(if(tkU=l«?”HnMki.!〃如果进行・值,作的两个对,是同一个対・,剜立即返圓〃むl・t・p;p%awckax[«trl«a(r.p)*l];atrcpr(p>r.p);c»««<\p«z*t*r=...*«p««adl;z«twa*tkia;)b谑mi*()(AZgUDMmNE");«2»1;〃自动调用自定义的・值•作函数”咽行体果।レ,…“』123496789•BaratszR...ijklmム1・W>...•!19I/O流端:数推的流动,抽&为"«*类C++的流奥岸提供了一回利用这些类可以实现计算机与外设之闾进行软帯交流・19.1printf和scant的缺陷琴美型安全,维译系统对函数原型进行检査(•敷个数、套敷类型),可以愚免许多巒决,但是・中系线对printf(»和sranfo函效只檢査第一个・数(,数个敬利类型信息包含在第一个・敬中),所以,其他的脩误无法在篇译时被发现.不可ザ充性,不能对类对然进行,入輸出・19.2I/。标准流类设取,从・施"中联取敬第写人,向“流a中添加敷据ie.tr...I(标扈”。流头文件,在慎文件中对各个流类定义了各自的全局对象.ciaiC”典供的标准輸入流对•名.对应启冬是一室C.«t:C”提供的标准輸出流对徵名,对应设善是解暮c・rr:Cせ提供的标應错杀流对象名,对应设答是屏幕cl«r.C-実供的标充打印流対拿名,对应设普是打印机例如,vi・是ht・・い流类的对象,创更谟时家时,传通蛤构造歯数的实參是“标准・入设餐(键量/,即设美的ー个数据成员是"«*«*,对&ci.的・设着名”是便段;-»•是i.tr.M类的事作符・假函数,执行“》”慷伟就从健會上或取ー个敷帑龄指定的丈量(函数的另ー个“效).•7416.原理M例:メ417的例题*&U,tZ2»eldfB(&ata*iatV){if(tasO)c«rr«*i

201co«t«aA««adl;}(M(20.2);£b(20,0);・•z•3•vat•霍・«*TVi■■■■1«cmmIImxe4ir«ctedl19.3文件流类飾―ゝ,・文件流”头文件,在快文件中对各个文件流类进行了定义,但是没有前定义各自的全局对れ•因为,在c-中文件类不是标准付善,不传價光定义.在买文件fstzs.h中飴出了£str«MiWs«<.ifstreaa.ofstx.a・、fa*r・s类的定义fitrawabM*fti{■<>•■・和ofatw.M!的公共茶类,£■t>•■・是ifatr-和・fatr・m・的派生昊,事知公有儀承美事.文件施奥的機祚(成员函斂)应用ダ外部收冬,量員量的、,帽用的R・・•进行文件掾作,必須创建文件流对ユ,创建文件流对W时必須旭定文件名和文件的打开方式(文件名和文件的打开方式ft伸递給构造函敷的实")“415构造函数,文件打开方式,文件保护方式1.打开文件只有打开文件,才可以访问文件(对文件流的对盆进行掾作)•过朗・1A”•■・、・A•・い、的对れ,在釵•时自动调用善自的帯•敏的构!ft函敷来打开文件I或者,对已有的流对家用・g・。函数来打开文件.创建i力”•・的对鈑,轶吿文件打开方式为-n”创建・f»tr・=的对th缺廿文件打开方式为"«<"制”f・幔•”的对th无候省文件打开方式,。須指定方式2.关闭文件1.调用公共碁类at”.j的一”・()成员国数注意,文件被关闭了,但ft・流(io];•“1,”2(ス上2&セつ;〃”1是个。—《«类的没有初始值的对家(没有打开文件)”l.op»(、bcl.dat>);〃对魚«>1i!用成员曲敷。》»0以缺省方式打开ー个文笄o*l«~*L,arkai12S”«,»11;〃向文件宀1.dat中耳人一行数据“2«”.12«71«ラi3-t・a*"«・メl;〃肉文件宀2.At中写人二行数据osl.cl.s«〇:•s2.cl.s«();isl.。(ゝbclatつ;Ml»*»b»i;

202c.»K<*«""«K<""«(i*2)«**il;isl.<1..•():〃关闭文件,但对霰ユI依依存在u!»«»«;fa(”宀l&t,i»a::・.り;〃以既叫法又叫写的方式打开文件£.»•»¥»»I〃厘先后文件指計指向ドー个c««l«*fa:•«»«**«¥«*w«i«»Ul;3pw-«777«・メ】;〃向文件ハcl.At中再写入一行数据£>.cleaa();fa.ope>(**Wl.dat*i«a::is):〃以只设方式打开文件£a»«»V>i;c««K<*«b:•«»«*-«b«*£a»a»k»i;c««K<*fa:«»«"«く"W«i««Ul;£a.cl»a«O;)/小行結果I>UBrUi24S99.12iieo^toar£a:aUarUi123fa:aUarUi123fa:UUkppp777«/说明i1.写入时以,入回车将わ记一行站京,使取时以空格或回车将分割数据单元2.加果构域函数或•数中指定的文件建立在饮程序的可执行文件所在的口景中,文件路径ザ道,否副必須指定文件篇程(路径分隔将用两个反斜杠l\\)19.4串流类c+・允许把字符申当作世善,进行时序源类对,的維入・出黒作・■t*■”••・卜义文件I包含阜流类““.”.・・■istrstrceM^•“,”.一・的定义在C”中申激类不是标准设备,不能預先定义例:>7420的例题#i>cl«dackar*paxs«Striar(ckax^pStriw)(istxstrcanixp(pS,*ia»«I»bex»Uluc«;diu・pB(pBBffer,12B);•wt>«*abmWxZ.«dhinkrくく,balances*«WlaAee«>\0*;〃必須加‘、。’,否则輸出不正。)(clax-セゴ12s4100.35*;cKax^BofspaxseStxi&r(stx);■K<>B

2032,用etO微取•・个字符S.用etO输入-系列字符4.輸出ー个字符19.7重载插入运算符C”提供的插入运算衿,«(是重赦运幫符而成的用戶可以再度修修入运算符,以完成特定的,出.“421例愿次紳:♦iaelwdA“红13くn,k>〃包含抑制粉对公的头文件,»/422classBIB(”blic:EB(厶・"•vtO.O)(rvuBr;jfB(^7(Ma)^100.04.55)•yerater&.£•()〃昊型转検メ敢(retwam4if/lO0,。;}。建diflylay(•■tx«Mko

20420模板模板,C++支持・斂化多あ性的工具•斂化多毒性I对程序中所处理的対,的类ボ«敷化20.1横板的概念C++的主♦构件是类和的数C++模板,函抬模板、美模板1.函敷模板和模板函敷函敷模板,定义ー个函数时,明須明事函數的近冋类型、参数的类型,这些类量如果被参数化,则该歯数的应用就广♦•敏化的函敷称为函敷模板.例如:i*taba(iatx){r«tw&s〃与一个渔数模板M收函敷,函敷模板是生成曲数代码的样板,当今数类量确定后,编译时用函数模板生成个具有・定类型的函数,这个由函数模板而生成的函数称为模板函数・例如:*iB£lUe-rT>TaU(Tx){reiwax<0?rM;)TwidnmIbO(iatbS"5;&・bl・dsY.5;c«Bt«aW(B)«e»^l;〃的译时生成£b,abo(iaix){…》模板fifi数coBt«aW(d)«e»ll;〃归译时生成ム*bhah■(ム・bレ(...)模板函数)/微行鮎果:59.S♦/2.类模板和模板类类模板:定义ー不类时,必须定义各成员的类型,这些类型加果被,效化,则谟类的应用就广,可以生成一包类.•效化的类称为类模板.例如:class1(iBtx;Vin):x(xx)0iatfa(){retwa});classB(ム・bl・x;pwblic:B(iovblexx):x(xx){)doublefat()fretwaa—〜;)):改成|cImbA{T»Mic:A(Th):x(u)0Tf»())模板拈类模板是生成类的样板,当鬓的“数关ホ・定后,编译时用类模板把类型叁效换成确定的类型,威生成一个只有痢定类型的类.这个由奥模板而生成的美称为模板类・

205例妬*iBcl«4s<<■»!<<•classA(Ts;»blic:A(In):s(»)0Tfa()(retwa;));(A«l(5);〃編译M生成一个ICT轉換成iat的模板美Al«>B2(5.9):〃*译M生成一个1ET转换成山3>l•的模板类c««t«al.**<<«2.;)ノ吸行結果:1251W.375•/20.2为什么要用横板冃的।・免点复・程,増加程序的艮活性20.3函数模板点明利定义,格式1,“»】•”函数返同类セ法数名(彩参列表)<...)说,,ー且声明了某个参数化类型名,谟类皇名就可以在歯数定义中被使用«.■立一个能幡处理多种类型的两个斂的乗法运算的款总模板«•«1.«•〃六明斷按在下面的兩敷cal0是个丽散横板T1eaKH.72ル〃决函«(模板有两个参数化的类型名,T1和12(r«tvaT1(**y);}(iat匸11;&»・£・E99;》《・U1;〃分别以实参い的类型iat和れ。バ曾按“敷化类型名!1*12“.1<〈=1(わ・)«・M1;〃分别以文,ヵ・的类型式”,和ia♦普拱・敷化类型名T1利!2)/・执行站果।10991099.S9•/20.4重載函数模板可以重載函敷模板,即函数名可以与函数模板名同名.p/442例电讲解T>eidf(T*^){p">f();c0・・<<・・・ーl・t.;}eidf(&b<>)(€•B♦«wf0,..;)classA(public:▼irt^aleidf0{c«>K<*£.,,*«eadl;};hclassB:pvblicAbK<*B.,•*««>il;}

206h(A*pa^avB;f(SSM);)/啾行陋果:・〇...5566template..••/说明IJK线先匹配・假函数,如果西配不成功,再匹配函敷模板20.4类横板的定义格式,tawl«t«claa|美名{…对广靠内联的成员函斂的定义格式|參数化类型名1类名(,敷化类P名1,•敷化类型名2套敷化美取名a>::成员函敷名(・敷列表)ノ44〜445例总誤解20.5使用类模板例]♦Mac»”'1N・く3-T,iat1>〃由明鷺搜在下面的类A是个类横板claaaA{T*[Y];p«Mic:AO;BidakovOBiaakO:);ta,l・t・くtR«aMNT,xa«1>A::AO{f»z(»tisO:xveiiA1>::»K(){fer(i>tiBO;iO;4^i){c1瞥换•敏化类型T.5替換■••«k();)〃执行时■入3个整融Sカ驚说明I类模板A中的T为,«[化了的奥里名II为,數化了的常量,决常量的異型カiバ型注依.在定义对象时必须加以实・类型说明.上例中的IA«;20.7使用标准模板类库:Josephus问题メ447

20721异常处理21.1异常的概念异常,指程序运行时出现了非常事件,泉统不知道如何处就,就中断执行・例如除斂为0.算常处香,希里引发异常时,儂幡解决异常,使将用序能"正需执行C■・ヰ,利用trア、tkrow>c.tc!兩句遊行异常处理异常是对所有健怖預料的运行恰黄进行处起的机制,使舞对运行鼻常加以控制21.2鼻常的苔本思想在被调用函数中"引发”界常・即如巣在被调用函敷的执行过集中出现异常,就把»常引发飴调用函数,并且立即退回,花・用党数屮"捕捉”鼻常.叩同用函敷働果收到被・用函敝引发的异常,就揖行相应的总ナ段处理这个异常.21.3异常的实现ノ43sIJK统(!用・"〇,对其中・妊。的・敷捕案异常并处屈异常异常处理的一般过程I1.对可能在运行时会出现穽常的地方通过tN”满句“引发.焼鼻常ItM・•K达式t说明:①表达式的类型被款为“异常”类型,弁常处理时就根据捕捉到的异常,按其类量不同而分制处理

208②只有在可能出现异常的地方马上ル•・语句,オ会引发异常,否則程序异常中断③对干的敷眞用,如果被•用的敷引发了异常,返回时不是回到调用点,而是返回到调用函故所指定的地方.1.m过帽,、。川c第句捕捉异常并处・异常,try{...诉句段方拳怆用诉句收I才・处产ン旬H2■McK鼻雷奥•声明1)レ・)“tcM异常类型声明2〃…异雷类型声明…kMUt-M句P)a其中."穽常类型声明.为佔计会引起鼻奮的鼻作数的类型・月直明福法为I敷僧类型标识相(««I敷裕奥量"标仪符》例,isc1vdaAsvble*“(ム3>1・.doubleb)t«Tr.3/O0='«4i.(7.尉0.0)«・31;S/l0=*«4iv(7.S,1.0)««»A1;)catck(ih«bl«)(ofムGdixmt.•\b;1co«K<*Tlatisok.}/微行納果:7.3/20=3fc5•sceptofdovidiar>«re.Oatis士W21.4异常的规则短則,l.セア和“tch是ー个・体性的密句,在trア段中捕捉异常,在stch段中处理异常.可以有多个“Hh段,即具有多个处理不同鼻客类型的程序段•etch段必加祟跟在”,段之后・2.c.tcM异常类量声明),(・鼻常昊鱼”必須育,•梶是瑁过对数相奧量造行兀配实现的S.如果通过th•・拍掷了一个异常,被捕捉到后,在本党敷中找不到与异常类型匹配的卜段,跳圮控制退回到・用函敷《父语敷)中,使用相同的畑喇在父函数中寻找相セ的处理程序鹿刎异常被处理,或を被C+4"运行系统处理(即异常終止).例।♦ixl3»Go・t”5.»i>*.iatb)(if(bsO)“,”ぐf>2仇..”《・>ai;〃一旦粕那"鼻常”,此句及以下语旬均不被执行iat〜iatb)(iat>;try(ce>t«()\»M;1»tck(^U)(e«Bt«MaiOi>Cl•ぃス)〃ーH捕捉到异客,就寻找异常处理界印c・3《"fs10…"《Z1;

209)(ist=88,y«0;try{ee*««Vyt“«&1(20«・b41;}catck(iB«)(ce>t«*miB():iatbtO\a":)〃此鼻常处處被执行c♦”《、1bO….くGbAI;)ノ啦行结果•&】()■B>B():iBigo■B>B()...*/4.异常处理完毕,立即执行处理本异常程序段所在的那个try语句后的语句.21.5多踣捕捉多鶏捕捉:,个程序中的所有类型的异常,都会被捕捉.用户定义的ー拗U一ー捕捉ーー处理异雷.构成一个异常区域,各个界・区城内发生的异常被本区域捕捉,焦后处理,如巣本区城内没有该鼻常类型的处域程序段,就由系就捕捉并处理,如果异常不是发生在用户定义的鼻電区城内,则由“航修梶井处理・被泰競捕捉的异常.均采用・中斯”执行来处理.“イ8例・许メ21.6异常处理机制异常处理机制:1.在ー个函数・调用儀・中,如果慑中的某个希敷通过&。・抽擦rー个异常,被捕捉到后,在本函数中找不到与异常类型匹配的c.uk段,iue控制退回到苗用函敷(父雷敷)中,使用相同的用!用住父メ敷申寻找相应的处理程序.…,直到异常被处理,或!tltc-は行泰彘处理(即异常终止)•异常处理完毕,立即执行处理本异常程序段所在的那个trア语句后的语句.2.如果&•・没有帯・数,則表示把捕捉到的・异常“再沿"駐”向上施■出去.,,如果出现0形式,叩事敢为省略号,是ー个与任何类型都匹配的默认异常处现程».・跃队,穽常处理程序段应慎耳在・后面,否明编/通不过•例14ise1wU&BtfB2(i>t.£b£U){if(bMO)tkrevb;ce>t«*fB2()...;retwba/b;)&BtfBl(iBt.iBtb)(iats;try{ce>t«*£Bl()\B*;■■42(〜i);)catck(doable)(&.ble\B*;)ce>l«*fBl()...*««adll;r«twBB;)。建miB()(iatsftB8,y«0;t»y(〃tkre.;〃如果写就语句.剜把鼻常椎抑蛤C一运行系読,格中断运行€•>♦«*»/*«£al;}c*tck(...){:dftfnltteO\a*;))ノ毋行结果,810mi>O:de£BBlt…■aia()ハ・♦/

21021.7使用异常的方法异常诙classA(v«blic:iat,ア;A(iat.1,iatyl){*5*1;rsyl;}eidsko*(){=3(<2::yS.<<メ<■*;));classB:gral»licA(i*Q-,;*«blic:B(iatb1>iatyl,iata2/aaty2):A(sl,yl)>x(x2),y(y2)0eidsk»*(){A::,レ・〇;c・3«F::>=~くく♦<~ys\

当前文档最多预览五页,下载文档查看全文

此文档下载收益归作者所有

当前文档最多预览五页,下载文档查看全文
温馨提示:
1. 部分包含数学公式或PPT动画的文件,查看预览时可能会显示错乱或异常,文件下载后无此问题,请放心下载。
2. 本文档由用户上传,版权归属用户,天天文库负责整理代发布。如果您对本文档版权有争议请及时联系客服。
3. 下载前请仔细阅读文档内容,确认文档内容符合您的需求后进行下载,若出现内容与标题不符可向本站投诉处理。
4. 下载文档时可能由于网络波动等原因无法下载或下载错误,付费完成后未能成功下载的用户请联系客服处理。
最近更新
更多
大家都在看
近期热门
关闭