c基础学习教程.pptx

上传人:莉*** 文档编号:87181617 上传时间:2023-04-16 格式:PPTX 页数:139 大小:371.08KB
返回 下载 相关 举报
c基础学习教程.pptx_第1页
第1页 / 共139页
c基础学习教程.pptx_第2页
第2页 / 共139页
点击查看更多>>
资源描述

《c基础学习教程.pptx》由会员分享,可在线阅读,更多相关《c基础学习教程.pptx(139页珍藏版)》请在taowenge.com淘文阁网|工程机械CAD图纸|机械工程制图|CAD装配图下载|SolidWorks_CaTia_CAD_UG_PROE_设计图分享下载上搜索。

1、第一节 c+概述main()函数标准输入输出流exit语句数据类型标准库string类型引用类型指针和const限定符动态内存分配第1页/共139页1.1 main()函数intmain()return0;每个c+程序必须含有main()函数,且main函数是唯一被操作系统显式调用的函数定义函数必须制定4个元素:返回类型、函数名、形参表、函数体。操作系统通过main的返回值来确定程序是否成功执行完毕,返回0表示程序成功执行完毕,通常非0表示有错误出现第2页/共139页1.2 标准输入输出流C+没有直接定义进行输入/输出的任何语句,这个功能由标准库提供。包含两个类:输入流istream和输出流o

2、stream.#includeusingnamespacestd;标准库中的四个IO对象cin标准输入(如键盘),为istream对象cout标准输出(如显示屏),为ostream对象cerr标准错误,用于输出警告和错误信息,为ostream对象clog用于产生程序执行的一般信息,为ostream对象第3页/共139页cin读入流(由键盘输入)作用从键盘取得数据送至内存,与一起使用结合方向为自左向右例如:intv1,v2;cinv1v2;从流中读取信息时,输入流缓冲指针跟踪最后一个读入到流的字符,每次尝试从流获取信息时,都从指针的当前位置开始qcin自动跳过空白字符(whitespace)q返

3、回值为左操作数第4页/共139页用cout写入到流(输出到屏幕)cout必须与输出操作符一起使用,结合方向为自左向右例如:coutEntertwonumbersendl;coutdecx;(hex/oct)作用将右操作数插入到cout中,可同时接受不同类型的数据输出,所以可有多个操作符,把信息写入流时,把信息添加到流的末尾,相当于从左到右输出endl(endofline)为操纵符,具有换行效果,并刷新与设备相关联的缓冲区,刷新后用户可立即看到写入到流中的输出。注:忘记刷新可能会造成输出停留在缓冲区,建议在程序员调试过程中,这些语句都应刷新输出流中,setw(n):为后面的输出项预留n列第5页/

4、共139页1.3 exit()语句形式:exit(interger_value);执行exit语句时,程序立即终止。一般来说,如果因为一个错误而调用exit,就使用1,其他情况使用0。该函数在头文件cstdlib中,所有要有预编译命令#includeusingnamespacestd;第6页/共139页1.4 内置数据类型常量宏常量:#definePI3.1415926系统不为其分配内存,只是简单的字符串替换const常量:const类型常量标识符=值;常量定义后不能修改,所以必须初始化例如:constdoublePI=3.1415926;系统为PI分配内存单元两种常量的比较const常量有数

5、据类型,而宏常量没有数据类型;编译器可以对const常量进行类型合法性检查,而对宏常量仅仅是字符的替换,没有合法性检查,并且在字符替换的时候可能产生意想不到的错误c+中,const常量完全可以取代宏常量第7页/共139页q布尔类型bool,它的值只有两个true和false可以将算术类型的任何值赋给bool对象。0代表false非0代表trueq初始化:创建对象并给它赋初值(赋值指擦除对象的当前值并用新值代替)有两种形式:复制初始化:用等号intval=1024;直接初始化:初始化式放在括号中intval(1024);通常在一个对象首次使用的地方定义该对象第8页/共139页1.5 标准库str

6、ing类型#includeusingnamespacestd;string对象的定义和初始化strings2(s1);/s1为string对象或字符串字面值strings3(n,c);/s3为n个c注意:字符串字面值和标准库string类型不是同一类型string对象的读写输入:cins;/从第一个非空字符读至下一个空白字符读入一行getline(cin,line);两个参数:输入流对象和string对象功能:从输入流的中读取内容到line中,换行符是该行的结束标志注:getline()不忽略开头的换行符,但line并不保存换行符,即若开头遇换行符,line为空stringq输出:coutse

7、ndl;第9页/共139页#include#includeusingnamespacestd;intmain(intargc,char*argv)stringstr;coutInputastringstr;/输入str的时候,只要遇到了空格,就会结束输入coutstrendl;coutInputalineusinggetlineendl;getline(cin,str);coutstrstr;输入了一次回车,这个语句遇到回车就结束,这样,回车符也跟着到了内存,到用getline()再输入时,内存里第一个字符就是回车,所以getline()一读到这个回车就结束了,所以getline(cin,st

8、r);不起作用。解决:处理掉cinstr;遗留的回车符,可以在该语句下加一句:getchar();/吸收内存里的回车符第10页/共139页string对象的操作s.empty();若字符串为空,返回trues.size();返回s中字符的个数qsn;返回s中位置为n的字符qs1=s2;比较,所有的比较运算符都可以使用qs1+=s2;连接qs1=s2;赋值,string类型可以和字符串字面值连接,赋给string类型,但是,+操作符的左右操作数必须至少有一个string类型strings=hello+,+s1;第11页/共139页1.6 引用类型引用就是对象的另一个名字,主要用于函数的形参引入v

9、oidswap(inta,intb)inttemp=a;a=b;b=temp;intmain()intx=10,y=20;swap(x,y);q形参与实参有各自不同的内存空间,若实参是一个复杂对象,重新分配内存会引起程序执行效率大大下降q形参对实参为值传递,对形参的任何改变不会引起实参值的改变第12页/共139页1.6.1 非const引用引用就是某一变量(目标)的一个别名,对引用的操作与对变量直接操作完全一样。声明:类型标识符&引用名=目标变量名;inta;int&ra=a;/定义引用ra,它是变量a的引用(别名)(1)&在此不是求地址运算,而是起标识作用。(2)声明引用时,必须同时对其进行

10、初始化。(3)引用声明完毕后,相当于目标变量名有两个名称,不能再把该引用名作为其他变量名的别名。(4)声明一个引用,不是新定义了一个变量,它只表示该引用名是目标变量名的一个别名,它本身不是一种数据类型,因此引用本身不占存储单元。故:对引用求地址,就是对目标变量求地址。&ra与&a相等。第13页/共139页非const引用intival=1024;1.引用必须在定义时初始化,int&refval=ival;一旦绑定到某对象不可以将引用int&refval1;绑定到另一对象int&refval2=refval;2.不能定义引用类型的引用,int&ref1=4;必须用与该变量同类型对象初始化int&

11、ref2=ival+5;3.引用对应的值必须具有相应的内存空间,以便对这个空间进行引用。常量、表达式、引用不能赋给引用例:inti=5;intj=6;int&k=i;k=j;/k和i的值都变成了6;第14页/共139页1.6.2 const引用格式:const 类型标识符&引用名=目标变量名;用这种方式声明的引用,不能通过引用对目标变量的值进行修改,从而使引用的目标成为const,达到了引用的安全性。int a;const int&ra=a;ra=1;/错误a=1;/正确引用型参数应该在能被定义为const的情况下,尽量定义为const。第15页/共139页 对const对象的引用consti

12、ntival=1024;inti=34;constint&refval=ival;refval=512;int&ref2=ival;constint&ref3=42;constint&ref=i;constint&ref4=ref3+3;vrefval是对const型的引用,所以任何对refval的赋值都是非法vconst对象必须用const引用vconst引用可以绑定到相关的类型的对象,或绑定到右值第16页/共139页1.6.3 指针和引用的比较指针和引用都可间接访问另一个值,但是1、引用总是指向某个对象,定义时必须初始化。指针则可以在任何时候被初始化2、引用一旦被初始化,就不能改变引用的关

13、系而指针则可以随时改变所指向的对象3、赋值:引用即为别名,给引用赋值修改的是该引用所关联的对象的值(非const引用)而指针可以更改其指向的对象,也可以更改所指向的对象的值4、不能有NULL引用,引用必须与合法的存储单元关联,而指针则可以是NULL第17页/共139页1.7 指针和const限定符使用const修饰指针时,由于const的位置不同,而含意不同。1.7.1指向const对象的指针指向const的指针,不可以通过该指针修改对象,但可以其他方式修改double dval=3.14,pi=3.1415;const double*ptr=&dval;/const限定了指针所指的对象类型,

14、非ptr*ptr=;/不合法 指针所指的对象不能改 ptr=π/合法,指针值可变dval=3.1415;/合法第18页/共139页若一个指针是指向const对象,则该指针必须具有const特性。例如constdoublepi=3.14159;constdouble*ptr=π/正确double*ptr1=π/错误,const对象要用指向const的指针来指向,这样可以保证既不能通过*ptr,也不能通过pi修改其值指向const的指针常用作函数的形参,这样可以确保函数的实参在函数调用过程中不被修改voiduse_ptr(constint*p)第19页/共139页1.7.2 co

15、nst指针固定指向一个对象的指针,即指针本身是常量char*const ptr1=stringptr1;/const放在类型说明和变量之间ptr1=stringptr2;/非法,指针本身的值不可改变*ptr1=m;/合法 指针所指的变量的值可以改变若指针及指针所指向的变量的值都不可以更改constchar*constptr=stringptr;第20页/共139页1.8 动态内存分配一内存分配有三种方式n从静态存储区域分配。内存在程序编译的时候就已经分配好,这块内存在程序的整个运行期间都存在。例如全局变量,static变量。n栈,就是那些由编译器在需要的时候分配,在不需要的时候自动清除的变量的

16、存储区。里面的变量通常是局部变量、函数参数等。栈内存分配运算内置于处理器的指令集中,效率很高,但是分配的内存容量有限。1.堆,亦称动态内存分配。程序在运行的时候用malloc或new申请任意多少的内存,程序员自己负责在何时用free或delete释放内存。动态内存的生存期由我们决定如果程序员没有释放掉,那么在程序结束后,操作系统会自动回收。第21页/共139页1.8.2 单个对象的动态分配与释放动态分配:由关键字new及其后面的类型指示符构成。该类型指示符可以是内置类型或class类型。例:newint;从堆中分配了一个int型的对象。newStudent;分配了一个Student类对象。需要

17、注意的是堆中分配的对象没有名字。new表达式返回了一个指向该对象的指针,对该对象的全部操作都要通过这个指针间接完成。例如:pint*pi=newint;该new表达式创建了一个int型的对象,由pi指向它。初始化int*pi=newint(0);该语句表示pi指向一个int型的对象,该对象的初始值为0。括号中的表达式被称作初始化式第22页/共139页动态内存的释放与静态分配内存的对象不同,编译器不会自动释放它们所占的内存-除非整个程序结束。所以当动态分配内存的对象完成它的使命,需要被销毁的时候不能依赖编译器,而要靠程序员用delete释放。格式:deletepi;/释放pi所指向的内存空间指针

18、pi本身是个在全局域中声明的全局对象,它的生命期由编译器控制。pi的存储区在程序开始之前就被分配,一直保持到程序结束。而pi指向的对象的生命期是由程序员控制的,它是在程序执行过程中遇到new表达式时才被创建,遇到delete表达式时被销毁并收回存储区第23页/共139页动态内存的释放delete只能用在指向内存是用new动态分配的指针上,如果将其在指向堆以外内存的指针上,会使程序运行期间出现未定义的行为。唯一的例外是,当指针指向NULL时,不管指针指向的对象是如何分配内存的,都不会引发麻烦。voidf()inti;char*str=asdd;int*pi=&i;short*ps=NULL;do

19、uble*pd=newdouble(123.3);deletestr;/危险!str指向的不是动态对象deletepi;/危险!pi指向的对象i是一个局部对象deleteps;/安全!ps指向NULLdeletepd;/安全!pd指向一个动态分配的对象第24页/共139页常见错误1忘记了释放内存,造成内存泄露。含有这种错误的函数每被调用一次就丢失一块内存。刚开始时系统的内存充足,你看不到错误。终有一次程序突然死掉,系统出现提示:内存泄漏(memoryleak)。函数体内的局部变量在函数结束时自动消亡。例如p是局部的指针变量,它消亡的时候会让它所指的动态内存一起消亡。这是错觉!voidFunc(

20、void)char*p=(char*)malloc(100);/动态内存会自动释放吗?指针消亡了,并不表示它所指的内存会被自动释放2对同一内存区应用了多次delete表达式。这通常发生在多个指针指向同一个动态分配对象的时候。若多个指针指向同一对象,当通过某一个指针释放该对象时就会发生这种情况。3内存被释放了,并不表示指针会消亡或者成了NULL指针,形成野指针第25页/共139页野指针因此,当程序执行deletepi;语句时,pi指向对象的内存被释放,但指针pi本身的内存并没有受到delete表达式的影响。在deletepi;之后,pi被称作空悬指针(俗称野指针),即指向无效内存的指针。空悬指针

21、是错误的根源,它很难被检测到,如果对它进行操作将会产生无法预测的结果。一个比较好的办法是在指针所指的对象被释放后,马上将该指针设置为NULL,这样可以清楚地表明该指针不再指向任何对象char*p=(char*)malloc(100);strcpy(p,“hello”);free(p);/p所指的内存被释放,但是p所指的地址仍然不变if(p!=NULL)/没有起到防错作用strcpy(p,“world”);/出错第26页/共139页野指针指针操作超越了变量的作用范围。这种情况让人防不胜防,示例程序如下:classApublic:voidFunc(void)cout“FuncofclassA”Fu

22、nc();/p是“野指针”第27页/共139页1.8.3 数组的动态分配与释放new表达式也可以在堆中分配数组。在这种情况下new表达式中的类型指示符后面必须有一对方括号,里面的值代表数组的长度,而且该数值可以是一个复杂的表达式。new表达式返回指向数组第一个元素的指针。动态分配数组只需指定类型和长度格式:new typesize;/size为数组元素的长度,可以是任意表达式。new返回指向新分配数组的第一个元素的指针。例如:int*p2;p2=new intn;qdelete 释放new分配的存储空间delete p;/表明p指向的是动态存储区的数组,如果遗漏,编译器无法发现错误第28页/共

23、139页int*pi=newint(1024);/分配单个int型的对象,用1024初始化int*pia=newint1024;/分配一个含有1024个元素的int型数组,未被初始化第29页/共139页第二节 函数参数传递函数返回值内联函数函数的重载第30页/共139页2.1 参数传递C+语言中,函数的参数和返回值的传递方式有三种:值传递、指针传递和引用传递。在调用函数时,对于每一个实参,其类型必须与对应的形参类型相同,或可被转换为该形参类型2.1.1普通的非引用形参为传值调用,调用时将实参的值赋给形参,而形参的任何改变不会改变实参voidswap(intp1,intp2)inttemp=p1

24、;p1=p2;p2=temp;调用时:inta=5,b=9;swap(a,b);/a、b并没有互换第31页/共139页 指针形参指针传递传递的是地址,函数可以通过指针赋值,修改指针所指向的对象的值void swap(int*p1,int*p2)int temp=*p1;*p1=*p2;*p2=temp;调用时怎么写?q1、若要保护指针指向的对象的值,则形参需定义为指向const对象的指针voiduse_ptr(constint*p)在函数体中,不能通过*p修改p指向的对象的值实参既可以为int*,也可以为constint*类型第32页/共139页2、如果输入参数采用“值传递”,由于函数将自动产

25、生临时变量用于复制该参数,调用结束释放所以该参数本来就无需保护,没有必要加const修饰。例如不要将函数voidFunc1(intx)写成voidFunc1(constintx)。同理不要将函数voidFunc2(Aa)写成voidFunc2(constAa)。其中A为用户自定义的数据类型。对于非内部数据类型的参数而言,象voidFunc(Aa)这样声明的函数注定效率比较低。因为函数体内将产生A类型的临时对象用于复制参数a,而临时对象的构造、复制、析构过程都将消耗时间。为了提高效率,可以将函数声明改为voidFunc(A&a),因为“引用传递”仅借用一下参数的别名而已第33页/共139页2.1

26、.2 引用形参引用的一个重要作用就是作为函数的参数。c语言中当有大块数据作为参数传递的时候,采用的方案往往是指针,在C+中又增加了一种同样有效率的选择(在某些特殊情况下又是必须的选择),就是引用void swap(int&p1,int&p2)/形参p1,p2都是引用 int p;p=p1;p1=p2;p2=p;当调用该函数,在相应的主调函数的调用点处,直接以变量名作为实参进行调用即可,而不需要实参变量有任何的特殊要求。如:对应上面定义的swap函数,相应的主调函数可写为:第34页/共139页main()int a,b;cinab;/输入a,b两变量的值swap(a,b);/直接以变量a和b作为

27、实参调用swap函数 couta b;/输出结果(1)被调函数的形参就成为原来主调函数中的实参变量或对象的一个别名来使用,所以在被调函数中对形参变量的操作就是对其相应的目标对象(在主调函数中)的操作。(2)使用引用传递函数的参数,在内存中并没有产生实参的副本,它是直接对实参操作;在传值调用中若传递的是对象,将调用拷贝构造函数。因此,当参数传递的数据较大时,用引用比用一般变量传递参数的效率和所占空间都好。第35页/共139页三种传递方式的比较值传递voidFunc1(intx)x=x+10;/形参的使用intn=0;Func1(n);/调用cout“n=”nendl;/n=0指针传递voidFu

28、nc2(int*x)(*x)=(*x)+10;/形参的使用intn=0;/调用Func2(&n);cout“n=”nendl;/n=10第36页/共139页引用传递:voidFunc3(int&x)x=x+10;intn=0;Func3(n);cout“n=”nendl;/n=10对比上述三个示例程序,会发现“引用传递”的性质象“指针传递”,而书写方式象“值传递”。实际上“引用”可以做的任何事情“指针”也都能够做,为什么还要“引用”这东西?答案是“用适当的工具做恰如其分的工作”。第37页/共139页const 引用若不希望在函数体中通过引用来修改实参,可以使用const引用intsearch(

29、constT&x)/x为实参的别名,不用重新开辟空间,且不允许对x进行修改boolisShorter(conststring&s1,conststring&s2)returns1.size()s2.size();一般将不需要修改的引用形参都定义为const引用,而且可以增强其灵活性。(对于非const形参,实参不能为const对象,也不能为字面值常量)第38页/共139页传递指向指针的引用void swap(int*&v1,int*&v2)/v1是一个引用,与指向int型对象相关联 int*v;v=v1;v1=v2;v2=v;调用:int*pa=&a;int*pb=&b;swap(pa,pb)

30、;第39页/共139页2.2 函数返回值在系统调用处将函数的返回值放在一个临时空间,在调用的地方使用该返回值(赋给一个变量或进行运算),调用语句执行完,释放临时空间1)返回引用:没有复制返回值,相反返回的是对象本身格式:类型标识符&函数名(形参列表)函数体非const引用Chain&Chain:delete(intk)const引用:不能更改返回值conststring&shorterString(conststring&s1,conststring&s1)returns1.size()s2.size()?s1:s2;一般来说,函数返回的引用是对函数的某个参数的引用,而这个参数本身也是引用类型

31、。第40页/共139页引用作为返回值,必须遵守以下规则:不能返回局部变量的引用。主要原因是局部变量会在函数返回后被销毁,因此被返回的引用就成为了无所指的引用,程序会进入未知状态。conststring&manip(conststring&s)stringret=s;returnret;第41页/共139页2.3 内联函数在程序执行函数调用时,要求在转去前要保护现场保存地址,转回后先要恢复现场,并按原来保存地址继续执行。因此,函数调用要有一定的时间和空间开销,影响其效率。特别是对于一些函数体代码不是很大,但又频繁地被调用的函数来讲,解决其效率问题更为重要。因此引入内联函数。内联函数的定义方法定义

32、内联函数的方法很简单,只要在函数定义的头前加上关键字inline即可。第42页/共139页inlineisNumber(charch);/函数原型声明inline即内联函数voidmain()charch;cin.get(ch);if(isNumber(ch)cout是数字字符endl;elsecout不是数字字符=0&ch=0&ch=9)?1:0.该函数在编译时被替代,这样就避免了频繁调用函数对栈内存重复开辟所带来的消耗。但是会增加目标程序代码量,进而增加空间开销,可见它是以空间换取时间。第43页/共139页说明:(1)定义内联函数只是一种请求,而不是命令编译器一定这么做(2)内联函数应该在

33、头文件中定义(3)inline只适合函数体内代码简单的函数使用,不能包含复杂的结构控制语句例如while、switch,并且内联函数本身不能直接调用递归函数(自己内部还调用自己的函数)。第44页/共139页2.4 函数重载重载可分为函数重载和运算符重载函数重载在C+程序中,可以将语义、功能相似的几个函数用同一个名字表示,即函数重载。这样便于记忆,提高了函数的易用性。例如函数EatBeef,EatFish,EatChicken可以用同一个函数名Eat表示,用不同类型的参数加以区别。voidEatBeef();/可以改为voidEat(Beef);voidEatFish();/可以改为voidEa

34、t(Fish);voidEatChicken();/改为voidEat(Chicken);第45页/共139页例如:intsum(inta,intb)doublesum(doublea,doubleb)调用重载函数时,编译器会根据实参的类型、个数、顺序去调用相应的函数。intsum1=sum(5,6);doublesum2=sum(3.4,5.6);注:仅仅返回类型不同是不行的第46页/共139页第三节 类和对象类的定义和实现类的静态成员类的对象的定义和使用类的成员函数构造函数与析构函数第47页/共139页第三节 类和对象类是一种复杂的数据类型,它是将不同类型的数据和与这些数据相关的操作封装在

35、一起的集合体。这有点像C语言中的结构,唯一不同的就是结构没有定义所说的“数据相关的操作”,即“方法”封装外部用户只能看到定义抽象行为的操作集合程序员通过数据变量维护对象内部的状态第48页/共139页3.1 类的定义和实现类的定义一般地分为说明部分和实现部分。说明部分是用来说明该类中的成员,包含数据成员的说明和成员函数的说明。“干什么”实现部分是用来对成员函数的定义。“怎么干”。类的一般定义格式如下:class类名/class是定义类的关键字,是种标识符,通常用字母C开头public:公有成员函数或数据成员的说明private:私有数据成员或成员函数的说明;/注意:分号不可缺第49页/共139页

36、类的定义访问权限修饰符或访问控制修饰符:公有的(public)、私有的(private)和保护的(protected)public:公有部分往往是一些操作(成员函数),它是提供给用户的接口功能。这部分成员不仅可以在类内被访问,也可以在类外被访问。private:私有部分通常是一些数据成员,描述该类中的对象的属性,用户是无法访问它们的,只有成员函数或经特殊说明的函数才可以引用它们,它们是被用来隐藏的部分。protected:可以被本类及其继承类使用第50页/共139页一个日期类定义的例子/类的说明部分,一般放在文件中classCdatepublic:voidsetDate(inty,intm,i

37、ntd);intIsLeapYear();voidPrint();private:intyear,month,day;/类的实现部分一般放在文件中#include“”voidCdate:setDate(inty,intm,intd)这里出现的作用域运算符:year=y;month=m;day=d;是用来标识某个成员函数是属于哪intCdate:IsLeapYear()个类,如果成员函数定义在类体外要使用作用域运算符:return(year%4=0&year%100!=0)|(year%400=0);voidCdate:Print();coutyearmontbdayendl;第51页/共139

38、页类的定义说明定义类时应注意的事项1)在类体中不允许对所定义的数据成员进行初始化。2)一般地,在类体内先说明公有成员,它们是用户所关心的,后说明私有成员,它们是用户不感兴趣的。在说明数据成员时,一般按数据成员的类型大小,由小至大说明,这样可提高时空利用率。3)习惯地将类定义的说明部分放在头文件中.h。而实现部分放在.cpp文件中第52页/共139页3.1.2 类的实现类成员函数的实现部分一般放在.cpp文件中,如果要在类外使用类中的实例变量或者在类外定义函数体,要使用作用域运算符,用来标识某个成员是属于哪个类的。格式返回值类型类名:函数名(参数列表)例如:voidCdate:setDate(i

39、nty,intm,intd)year=y;month=m;day=d;第53页/共139页作用域运算符classPlayingCardpublic:enumSuitsSpade,Diamond,Club,Heart;Suitssuit()returnsuitValue;intrank()returnrankValue;private:SuitssuitValue;intrankValue;booleanfaceUp;;如:在类定义之外使用表示花色的常量()=PlayingCard:Diamond)第54页/共139页3.2 类的静态成员被一个类的所有实例共享的公共数据成员。静态成员(stati

40、c)可以实现同一个类的多个对象之间的数据共享。静态数据成员对于类的所有对象只开辟了一块内存空间(在静态存储区),其中一个对象对其改变,保证所有对象存取的是更新后的相同的值。静态数据成员的使用方法和注意事项如下:1、定义:静态数据成员在定义或说明时前面加关键字static。2、初始化:格式如下::=:u初始化在类体外进行,前面不加static和访问权限控制符private,public等。u初始化时使用作用域运算符来标明它所属类,因为静态数据成员是类的成员,而不是对象的成员。u静态数据成员是静态存储的,必须对它进行初始化。3、引用:第55页/共139页classMyclasspublic:Myc

41、lass(inta,intb,intc);voidGetNumber();voidGetSum();private:intA,B,C;staticintSum;实现intMyclass:Sum=0;Myclass:Myclass(inta,intb,intc)A=a;B=b;C=c;Sum+=A+B+C;调用MyclassM(3,7,10),N(14,9,11);第56页/共139页3.3类的对象的定义和使用u对象的定义有两种方法vclass类名对象名;2.也可以先声明类,然后定义类的对象类名对象名;编译系统为对象分配内存并且将这段内存空间与对象名称进行绑定,并进行必要的初始化操作.变量声明只

42、是创建了一个标识变量的名称,大部分面向对象语言通过new操作符来创建对象,c+语言可以将他们结合起来如PlayingCardaCard;/在java中必须写成PlayingCardaCard=newPlayingCard();第57页/共139页使用对象:在调用成员函数时,必须指明对类的哪个对象进行操作。利用成员运算符.表明从属关系,用于类的对象例如:Cdatedate,*p;date.setDate(2007,7,20);p=&date;p-IsLeapYear();/等价于();第58页/共139页3.4 类的成员函数成员函数的定义和声明:类的所有成员必须在类定义的内声明。类的成员函数既可

43、以在类内定义,以可以在类外定义,他可以访问该类的private成员如:boolsame_isbn(constSalesItem&r)constreturnisbn=;没有前缀的isbn指的是用于调用函数的对象的isbnq调用调用函数时,实际是使用对象来调用的if(total.same_isbn(trans)/r是trans的引用第59页/共139页this指针每个成员函数都有一个额外的、隐含的形参将该成员函数与调用该函数的类对象绑定在一起,这个形参为this。调用成员函数时,形参this初始化为调用函数的对象的地址。所以(trans)可以理解为same_isbn(&total,trans)/第

44、一个参数为隐含的,它传递的是调用对象的地址使用this在函数体中可以显式地使用boolsame_isbn(constSalesItem&r)constreturnthis-isbn=;第60页/共139页当成员函数中函数参数与数据成员同名时,需要this指针classPlayingCardPlayingCard(intsuit,intrank)this-rank=rank;this-suit=suit;this-faceUp=true;第61页/共139页 const成员函数使用const关键字进行说明的成员函数为常成员函数。只有常成员函数才有资格操作常量或常对象,没有使用const关键字说明

45、的成员函数不能用来操作常对象。说明格式如下:类型说明符 函数名(参数表)const;其中,const是加在函数说明后面的类型修饰符,它是函数类型的一个组成部分,因此,在函数实现部分也要带const关键字。任何不会修改数据成员的函数都应该声明为const类型。如果在编写const成员函数时,不慎修改了数据成员,或者调用了其它非const成员函数,编译器将指出错误,这无疑会提高程序的健壮性。第62页/共139页class Stackpublic:void Push(int elem);int Pop(void);int GetCount(void)const;/const成员函数private:i

46、nt m_num;int m_data100;int Stack:GetCount(void)const+m_num;/编译错误,企图修改数据成员m_numPop();/编译错误,企图调用非const函数return m_num;第63页/共139页3.5构造函数与析构函数概述构造函数的初始化表缺省的构造函数缺省的拷贝构造函数运算符重载缺省的赋值函数析构函数第64页/共139页3.5.1 概述每个类只有一个析构函数和一个赋值函数,但可以有多个构造函数(包含一个拷贝构造函数,其它的称为普通构造函数)。对于任意一个类A,如果不想编写上述函数,C+编译器将自动为A产生四个缺省的函数,如A();/缺省

47、的无参数构造函数A(constA&a);/缺省的拷贝构造函数A();/缺省的析构函数A&operate=(constA&a);/缺省的赋值函数第65页/共139页作用:把对象的初始化工作放在构造函数中,把清除工作放在析构函数中。当对象被创建时,构造函数被自动执行。当对象消亡时,析构函数被自动执行。这样可以自动执行对象的初始化和清除工作。命名:构造函数、析构函数与类同名,由于析构函数的目的与构造函数的相反,就加前缀以示区别。构造、析构函数没有返回值,即使是void也不可以。构造、析构函数置于类定义的public部分析构函数不得带有任何参数构造函数可以有一个或多个,一旦定义一个有参的构造函数,一定

48、要显式定义一个无参构造函数第66页/共139页3.5.2 构造函数的初始化表v和其他函数不同,构造函数有个特殊的初始化方式叫“初始化表达式表”(初始化表)。初始化表位于函数参数表之后,以冒号开始,后面接数据成员列表,列表之间用逗号分隔,每一个变量后面用一对圆括号包含它的初始值。v初始化表放在构造函数的定义中PlayingCard:PlayingCard(Suitsis,intir):suit(is),rank(ir),faceUp(true)/函数体 第67页/共139页(2)执行顺序首先执行初始化列表,然后执行该构造函数函数体中的语句成员对象初始化的次序完全不受它们在初始化表中次序的影响,只

49、由成员对象在类中声明的次序决定。这是因为类的声明是唯一的,而类的构造函数可以有多个,因此会有多个不同次序的初始化表。如果成员对象按照初始化表的次序进行构造,这将导致析构函数无法得到唯一的逆序。例classxinti;intj;public:x(intval):j(val),i(j)/相当于i=j;j=val;j还没有初值就被使用;所以尽量避免使用成员来初始化其他成员x(intval):j(val),i(val)第68页/共139页const数据成员const数据成员只在某个对象生存期内是常量,而对于整个类而言却是可变的,因为类可以创建多个对象,不同的对象其const数据成员的值可以不同。不能在

50、类声明中初始化const数据成员。以下用法是错误的,因为类的对象未被创建时,编译器不知道SIZE的值是什么。classAconstintSIZE=100;/错误,企图在类声明中初始化const数据成员intarraySIZE;/错误,未知的SIZE;const数据成员的初始化只能在类构造函数的初始化表中进行,类的定义classAA(intsize);/构造函数constintSIZE;类的实现A:A(intsize):SIZE(size)/构造函数的初始化表生成类的对象Aa(100);/对象a的SIZE值为100Ab(200);/对象b的SIZE值为200第69页/共139页(3)使用说明大多

展开阅读全文
相关资源
相关搜索

当前位置:首页 > 应用文书 > PPT文档

本站为文档C TO C交易模式,本站只提供存储空间、用户上传的文档直接被用户下载,本站只是中间服务平台,本站所有文档下载所得的收益归上传人(含作者)所有。本站仅对用户上传内容的表现方式做保护处理,对上载内容本身不做任何修改或编辑。若文档所含内容侵犯了您的版权或隐私,请立即通知淘文阁网,我们立即给予删除!客服QQ:136780468 微信:18945177775 电话:18904686070

工信部备案号:黑ICP备15003705号© 2020-2023 www.taowenge.com 淘文阁