OOPC类成员学习教程.pptx
6 类成员(二)6.1 成员变量与成员函数6.2 this指针6.3 成员对象6.4 const(常量)6.5 const对象与const成员函数6.6 静态成员变量与静态成员函数第1页/共31页6.4 const量量(常量常量)从高质量程序设计的角度考察从高质量程序设计的角度考察C+C+中的中的constconst!第2页/共31页6.4.1 const的意义F最低权限原则:软件工程的基本原则之一软件工程的基本原则之一。const的意义:在可更改与不可更改之间画一在可更改与不可更改之间画一条明确的界线,提高程序的安全性和可控性。条明确的界线,提高程序的安全性和可控性。eg:const int i=100;i+;/编译错误 第3页/共31页6.4.2 C中的const(常量)F“一个不能被改变的普通变量”。F因此:-总是占用存储;总是占用存储;-名字是全局的。也就是说,默认情况下,名字是全局的。也就是说,默认情况下,constconst是外部连接的是外部连接的(容易引起容易引起“名字冲突名字冲突”)。const int bufsize;/无需初始化 const int bufsize=100;char bufbufsize;/error!Why?在编译时,编译器并不知道在编译时,编译器并不知道constconst的值,它只是的值,它只是一个一个“运行时常量运行时常量”。第4页/共31页6.4.3 C+的ConstF通常,通常,C+C+编译器不为编译器不为constconst创建存储空间,而是把它创建存储空间,而是把它保存在保存在“符号表符号表”里,即里,即“编译时常量编译时常量”。const int bufsize;/非法,未赋初值 const int bufsize=100;char strbufbufsize;/OK,Why?F默认情况下,默认情况下,C+C+中的中的constconst是内部连接的,也就是说,是内部连接的,也就是说,constconst仅在仅在constconst被定义过的文件里才是可见的。(因此,被定义过的文件里才是可见的。(因此,不用担心名字冲突)不用担心名字冲突)F当定义一个当定义一个constconst时,必须赋一个值给它,除非用时,必须赋一个值给它,除非用externextern做出了清楚的说明。当用做出了清楚的说明。当用externextern说明了说明了constconst时,时,编译器会强制为编译器会强制为constconst分配空间,而不是保存在符号表分配空间,而不是保存在符号表中。中。extern const int bufsize;/未赋初值,但未赋初值,但externextern声明声明 了了bufsizebufsize在另在另一个文件一个文件 中定义及赋初值。中定义及赋初值。第5页/共31页6.4.3 C+的Const(续)Fconstconst用于集合,必须为其分配内存,用于集合,必须为其分配内存,(因为编译器因为编译器“不愿意不愿意”把集合保存到符号表中,太复杂把集合保存到符号表中,太复杂)。const int i=1,2,3,4;float fi3;/非法,编译期间无法知道存储空间非法,编译期间无法知道存储空间的值。的值。struct S int i,j;const S s=1,2,3,4 ;double ds1.j;/非法,理由同上非法,理由同上 int main()/:第6页/共31页6.4.4 C+中const的作用G值替代:C+C+的的constconst vs C C中的宏替换中的宏替换#define BUFSIZE 100;/宏替换 char strBUFSIZE;vs const int bufsize=100;/C+的const char strbufsize;L在宏替换中,在宏替换中,BUFSIZEBUFSIZE没有类型信息,不能进行类型检查;没有类型信息,不能进行类型检查;L宏定义是全局的,容易名字冲突。宏定义是全局的,容易名字冲突。第7页/共31页6.4.4 C+中const的作用(续)A 安全性 如果如果想用想用运行期间产生的值初始化运行期间产生的值初始化一个变量,并一个变量,并且知道在该变量的生命期内其值不变,则可用且知道在该变量的生命期内其值不变,则可用constconst限限定该变量,达到最大限度地保证改变量安全性的目的。定该变量,达到最大限度地保证改变量安全性的目的。int main()cout type a character&CR:;const char c=();/用运行期间产生的值初始化,之后不变 const char c2=c+a;cout c2;/:第8页/共31页6.4.5 const的应用:const指针1.指向const的指针(指针指向的内存地址的值不能改变指针指向的内存地址的值不能改变)const int*u;/u/u是一个指针,它指向是一个指针,它指向const int;const int;int const*v;/v/v是一个指向恰好是是一个指向恰好是constconst的的intint的的 普通指针;普通指针;2.const指针(指针的值不能改变指针的值不能改变)const int d=1;int*const w=&d;/w/w是一个指针,这个指针是是一个指针,这个指针是 指向指向intint的的constconst指针指针 注意:注意:C+C+中,中,constconst指针必须赋初值指针必须赋初值第9页/共31页6.4.5 const的应用:const指针(续)3.const指针指向const对象 int d=1;const int*const x=&d;int const*const x2=&d;/x,x2,*x,*x2/x,x2,*x,*x2都不能改变都不能改变第10页/共31页F非非constconst对象的地址可以赋给对象的地址可以赋给constconst指针;指针;Fconstconst对象的地址绝不可以赋给非对象的地址绝不可以赋给非constconst指针。指针。(因为这样做可能导致通过非因为这样做可能导致通过非constconst指针改变指针改变constconst对对象的值的后果象的值的后果)int d=1;const int e=2;int*u=&d;/OK-d not const/!int*v=&e;/illegal-e constint*w=(int*)&e;/legal but bad practiceint main()/:注意第11页/共31页6.4.6 const的应用:const参数1.传递const值 void f1(const int i)i+;/编译时错误,i不能改变 “形参形参”不能被改变不能被改变 or “or “实参实参”不能被改变?不能被改变?第12页/共31页6.4.7 const的应用:const返回值2.按值返回内部const 常量 int f3()return 1;const int f4()return 1;/返回const int;int main()const int j=f3();/Works fine int k=f4();/But this works fine too!/:对内部类型来说,按值返回对内部类型来说,按值返回constconst量并没有什么特别的意量并没有什么特别的意义义。第13页/共31页6.4.7 const的应用:const返回值(续)3.按值返回自定义类型的const:实际上阻止了返回值作为左值出现。实际上阻止了返回值作为左值出现。class X int i;public:X(int ii=0);void modify();X:X(int ii)i=ii;void X:modify()i+;第14页/共31页X f5()X x(2)return x;/返回变量返回变量const X f6()return X();/按值返回按值返回const;void f7(X&x)/按值传递非按值传递非const引用引用 ();int main()f5()=X(1);/正确,正确,f5()返回非返回非const量;量;f5().modify();/正确正确 f7(f5();/可能会有可能会有Warning,跟编译选项有关跟编译选项有关 f6()=X(1);/Error:f6()是常量,不能作左值是常量,不能作左值 f6().modify();/Error:f6()是常量,不能被修改是常量,不能被修改 f7(f6();/Error:Why?/:error 2664:cannot convert parameter 1 from const class X to class X&第15页/共31页6.4.7 const的应用:const指针4.传递和返回const指针 char*strcpy(char*dest,const char*src);void t(int*)void u(const int*cip)*cip=2;/Error:试图改变值 int i=*cip;/OK-copies value int*ip2=cip;/Error:试图让非const*指向 const *const int*const w()static int i;return&i;/返回静态局部量的地址第16页/共31页int main()int x=0;int*ip=&x;const int*cip=&x;t(ip);/OK /!t(cip);/Not OK u(ip);/OK u(cip);/Also OK /!int*ip2=w();/Not OK const int*const ccip=w();/OK const int*cip2=w();/OK /!*w()=1;/Not OK/:当传递一个或返回一个地址时(指针或引用),设置为const可以阻止客户程序员修改其值。第17页/共31页F对参数传递而言,C+建议用const引用传递替代值传递。问:有什么好处?答:兼顾了效率和易用性 传递地址比传递整个对象更有效;传递地址比传递整个对象更有效;引用传递比指针传递形式上更简单。引用传递比指针传递形式上更简单。第18页/共31页作业:8.5(上机)8.16(上机)第19页/共31页6.5 const对象与对象与const成员函数成员函数本节讨论本节讨论const在类中的应用在类中的应用Fconst数据成员数据成员Fconst成员函数成员函数Fconst对象对象第20页/共31页6.5.1 const数据成员class Fred const int size;public:Fred(int sz);void print();Fred:Fred(int sz):size(sz)void Fred:print()cout size=0&qnum=lastquote)n qnum=rand()%qsize;n return quoteslastquote=qnum;nnint main()n Quoter q;n const Quoter cq;n ();/OKn/!();/Not OK;non const functionn for(int i=0;i 20;i+)n cout ()endl;n/:第28页/共31页小结Fconstconst能将对象、函数参数、返回值和成员函数能将对象、函数参数、返回值和成员函数定义为常量,还可以进行值替代。定义为常量,还可以进行值替代。Fconstconst为程序设计提供了又一种非常好的类型检为程序设计提供了又一种非常好的类型检查形式及安全性。查形式及安全性。Fconstconst几乎成了程序正确性的几乎成了程序正确性的“救命稻草救命稻草”。第29页/共31页作业:P366(中文版P196):8.24(上机)8.28(提示:参考11.1)第30页/共31页感谢您的观看!第31页/共31页