资源描述
第五章 数据的共享与保护p作用域与可见性作用域与可见性p对象的生存期对象的生存期p静态成员静态成员p友元友元p共享数据的保护共享数据的保护p多文件结构和工程多文件结构和工程p编译预处理命令编译预处理命令作用域p作用域作用域 函数原型作用域函数原型作用域 函函数数原原型型作作用用域域开开始始于于函函数数原原型型声声明明的的左左括括号号“(”,结结束束于于右右括括号号“)”。例例如如:double Area(double length,double width);函数原型作用域是函数原型作用域是C+程序中最小的作用域。程序中最小的作用域。由由于于形形参参length和和width只只在在括括号号之之内内有有效效,在在程程序序的的其其它它地地方方无无法法引引用用这这个个标标识识符符,如如果果要要引引用用,必必须须重重新新定定义义。因因此此,这这里里的的标标识识符符length和和width实实际际上上是是可可有有可可无无的的,省省去去它它,也也决决不不会会影影响响到到程程序序的的编编译译和和运运行行结结果果。例例如如:double Area(double,double);p 块作用域块作用域又又称称局局部部作作用用域域。由由一一对对花花括括号号“”所所括括起起来来的的块块中中声声明明的的标标识识符符的的作作用用域域从从声声明明处处开开始始,一一直直到到块块结结束束的的花花括号为止。例如:括号为止。例如:void main()void fun1();int n;for(int i=0;i5;i+)int m;if(i%2)n+;m=n/2;/错误,错误,m未定义未定义 n=i;fun1();/fun1()函数调用函数调用 void fun1()couti=im表达式,其中表达式,其中ptr为指向为指向X类的对象的指针。类的对象的指针。p文件作用域文件作用域#includeint k;/全局全局变量,具有文件作用域量,具有文件作用域void main()k=5;k+;int k=7;k+;coutk=k;cout“,k=kendl;p命名空命名空间作用域(同文件作用域)作用域(同文件作用域)具有命名空具有命名空间作用域的作用域的变量即全局量即全局变量量程序运行结果为:程序运行结果为:k=8,k=6作用域作用域#include using namespace std;int i;/全局变量全局变量Namespace Nsint j;int main()i=5;Ns:j=6;using namespace Ns;int i;i=7;cout“i=”iendl;cout“j=”jendl;cout“i=”iendl;return 0;可见性p程程序序运运行行到到某某一一点点,能能够够引引用用到到的的标标识识符符,就就是是该处可见的标识符。该处可见的标识符。p可见性遵循的一般规则:可见性遵循的一般规则:标识符在标识符在引用前必须先声明引用前必须先声明。在在互互相相没没有有包包含含关关系系的的不不同同作作用用域域中中声声明明同同名名的的标标识识符时,两标识符符时,两标识符互不影响互不影响。如如果果在在两两个个或或多多个个具具有有包包含含关关系系的的作作用用域域中中声声明明了了同同名标识符名标识符,则,则外层标识符在内层不可见外层标识符在内层不可见。p对象对象(变量变量)的生存期的生存期对象或变量从产生到结束的这段时间称为它的生存期;对象或变量从产生到结束的这段时间称为它的生存期;生存期分类:静态生存期和动态生存期生存期分类:静态生存期和动态生存期p静态生存期静态生存期如果对象的生存期与程序的运行期相同,称其具有静态生存期;如果对象的生存期与程序的运行期相同,称其具有静态生存期;具有具有文件作用域文件作用域的变量的变量(全局变量全局变量)具有静态生存期。具有静态生存期。如如果果要要在在函函数数内内部部的的块块作作用用域域中中使使用用关关键键字字static修修饰饰的的对对象象,即即静静态对象,具有静态生存期。态对象,具有静态生存期。例如:例如:static int k;p动态生存期动态生存期除了上述两种情况,其余的对象都具有动态生存期。除了上述两种情况,其余的对象都具有动态生存期。块作用域中声明的具有动态生存期的对象,习惯称为局部对象;块作用域中声明的具有动态生存期的对象,习惯称为局部对象;动态生存期对象动态生存期对象(变量变量)开始于声明点,结束于标识符作用域结束处。开始于声明点,结束于标识符作用域结束处。对象的生存期对象生存期举例:举例:#include class Clockpublic:Clock();Clock(Clock&c);void SetTime(int newH,int newM,int newS);void ShowTime();Clock();private:int Hour,Minute,Second;Clock:Clock()Hour=0;Minute=0;Second=0;cout“构造函数被调用构造函数被调用”endl;对象生存期Clock:Clock(Clock&c)Hour=c.Hour;Minute=c.Minute;Second=c.Second;void Clock:SetTime(int newH,int newM,int newS)Hour=newH;Minute=newM;Second=newS;void Clock:ShowTime()cout Hour“:”Minute“:”Secondendl;Clock globClock;/声明对象声明对象globClock,具有静态生存期,文件作用域具有静态生存期,文件作用域void main()globClock.ShowTime();/引用具有文件作用域的对象引用具有文件作用域的对象globClock.SetTime(8,30,30);Clock myClock(globClock);/声明一个具有块作用域的对象声明一个具有块作用域的对象myClock.ShowTime();/end of 类的静态成员 是同一个类的不同对象之是同一个类的不同对象之间的数据和函数共享的机制。间的数据和函数共享的机制。静态数据成员p 实例属性实例属性 一个类的所有对象具有相同的属性,是指属性的个数、一个类的所有对象具有相同的属性,是指属性的个数、名称、数据类型相同,各个对象的属性值则可以各不名称、数据类型相同,各个对象的属性值则可以各不相同,并可随着程序的执行而变化,这样的属性称为相同,并可随着程序的执行而变化,这样的属性称为实例属性。实例属性。是区分同一个类中不同对象的属性是区分同一个类中不同对象的属性p 类属性类属性类属性是描述的类的所有对象共同特征的一个数据项类属性是描述的类的所有对象共同特征的一个数据项对于任何对象实例,它的属性值都相同。对于任何对象实例,它的属性值都相同。静态数据成员p 类属性的实现机制类属性的实现机制静态数据成员静态数据成员p 静态数据成员:静态数据成员:在类定义中,用关键字在类定义中,用关键字static修饰的数据成员,称为类修饰的数据成员,称为类的静态成员。的静态成员。p 静态数据成员与一般数据成员的区别静态数据成员与一般数据成员的区别对类的一般的数据成员,每个对象都有一份拷贝,即对类的一般的数据成员,每个对象都有一份拷贝,即每个对象的同名数据成员可以分别存储不同的数值每个对象的同名数据成员可以分别存储不同的数值;对于类的静态数据成员,每个类只有一份拷贝,即每对于类的静态数据成员,每个类只有一份拷贝,即每个对象的同名静态成员的取值都相同,由所有的对象个对象的同名静态成员的取值都相同,由所有的对象共同维护和使用。共同维护和使用。静态数据成员p 静态数据成员的声明、初始化和使用静态数据成员的声明、初始化和使用静态数据成员具有静态生存期静态数据成员具有静态生存期;引用性声明引用性声明:在类定义中只给出引用性声明,一般形式在类定义中只给出引用性声明,一般形式为为:static 类型名类型名 静态数据成员名静态数据成员名;访问访问:由于静态数据成员不属于任何一个对象,因此对由于静态数据成员不属于任何一个对象,因此对它的访问只需通过类名进行它的访问只需通过类名进行(只需指明它所属的类,不只需指明它所属的类,不必指明它是哪个对象的必指明它是哪个对象的),一般格式是,一般格式是 类名类名:静态数据成员名静态数据成员名定义性说明和初始化定义性说明和初始化:在文件作用域内,使用类名限定在文件作用域内,使用类名限定进行定义性说明,这时也可以初始化。进行定义性说明,这时也可以初始化。程序实例:程序实例:S5_2静态成员函数p 静态成员函数静态成员函数用关键字用关键字static声明的成员函数,称为类的静态成员函声明的成员函数,称为类的静态成员函数。静态成员函数同样也属于整个类数。静态成员函数同样也属于整个类(只有一个拷贝只有一个拷贝),由一个类的所有对象共同维护,为该类的所有对象所由一个类的所有对象共同维护,为该类的所有对象所共亨。共亨。p 对静态成员函数的访问对静态成员函数的访问对于公有的静态成员函数,可以通过类名,也可以通对于公有的静态成员函数,可以通过类名,也可以通过对象名来调用。过对象名来调用。即类名即类名:静态成员函数静态成员函数 或或 对象名对象名.静态成员函数静态成员函数注意注意:一般成员函数只能通过对象名来访问。一般成员函数只能通过对象名来访问。静态成员函数p 访问对象的数据成员和成员函数访问对象的数据成员和成员函数静态成员函数可以直按访问该类的静态数据成员和函静态成员函数可以直按访问该类的静态数据成员和函数成员数成员;而访问非静态的数据成员,必须通过参数传递而访问非静态的数据成员,必须通过参数传递方式得到对象名方式得到对象名(没有没有this),然后通过对象名来访问。,然后通过对象名来访问。主要用途主要用途:与静态数据成员协同使用,达到对同一个类与静态数据成员协同使用,达到对同一个类中对象之间共享数据进行维护的目的。中对象之间共享数据进行维护的目的。程序实例:程序实例:S5_3友元p 友元友元-类的亲密朋友类的亲密朋友能够直接访问一个类的数据成员和成员函数,称为友元。能够直接访问一个类的数据成员和成员函数,称为友元。p友元的作用友元的作用提供了不同类或对象的成员函数之间、类的成员函数与一般提供了不同类或对象的成员函数之间、类的成员函数与一般函数之间进行数据共亨的机制。函数之间进行数据共亨的机制。友员加强了函数与函数之间、类与类之间的相互联系友员加强了函数与函数之间、类与类之间的相互联系(好处好处/坏处坏处?)提高了程序的效率提高了程序的效率;但破坏了类的封装性,提高了共但破坏了类的封装性,提高了共亨性,这样的共享可能给程序的重用和扩充埋下隐患。亨性,这样的共享可能给程序的重用和扩充埋下隐患。p友元的种类友元的种类友员函数:如果友元是一般的函数或是类的成员函数,称为友员函数:如果友元是一般的函数或是类的成员函数,称为友元函数。友元函数。友员类:如果友员是一个类,称为友元类。此时友元类的所友员类:如果友员是一个类,称为友元类。此时友元类的所有成员函数都成为友元函数。有成员函数都成为友元函数。友元函数p友元函数:友元函数:友元函数是在类定义中由关键字友元函数是在类定义中由关键字friend修饰的非成员函修饰的非成员函数。数。可以是普通函数或其它类的成员函数可以是普通函数或其它类的成员函数 注意:注意:不管是哪一种,它都不是本类的成员函数不管是哪一种,它都不是本类的成员函数!但是在它的函数体中可以通过对象名访问类的私有但是在它的函数体中可以通过对象名访问类的私有成员和保护成员,而不必通过类的外部接口。成员和保护成员,而不必通过类的外部接口。程序示例:程序示例:S5_4友元类p 友元类友元类一个类一个类A可以用关键字可以用关键字friend声明为另一个类声明为另一个类B的友元,这时称类的友元,这时称类A为类为类B的友元类。此时,类的友元类。此时,类A的所有成员函数都是类的所有成员函数都是类B的友元函的友元函数。数。class B friend class A /类类A是类是类B的友元类的友元类;友元关系不具有传递性,如果类友元关系不具有传递性,如果类B是类是类A的友元,类的友元,类C是类是类B的友的友元,类元,类C与类与类A之间,如果没有声明,就没有友元关系;之间,如果没有声明,就没有友元关系;友元关系不具有对称性友元关系不具有对称性(单向性单向性),如果类,如果类B是类是类A的友元,类的友元,类B的的成员函数可以访问类成员函数可以访问类A的私有和保护成员,反之不行。的私有和保护成员,反之不行。友元类示例:友元类示例:S5_5共享数据的保护p 虽然数据隐藏保证了数据的安全性,但各种形式虽然数据隐藏保证了数据的安全性,但各种形式的数据共享却又不同程度的破坏了数据的安全。的数据共享却又不同程度的破坏了数据的安全。因此,对于既需要共享又需要防止改变的数据应因此,对于既需要共享又需要防止改变的数据应该声明为该声明为常量常量,运行期间不能改变。,运行期间不能改变。p 声明对象时也可以用声明对象时也可以用const修饰,称之为常对象。修饰,称之为常对象。常对象p常对象必须进行初始化,而且不能被更新。常对象必须进行初始化,而且不能被更新。p常对象定义的一般形式常对象定义的一般形式:类名类名 const 对象名对象名例例:class Apublic:A(int i,int j)x=i;y=j;private:int x,y;A const a(2,3);const A b(a);用const修饰的对象成员p 常成员函数常成员函数使用使用const关键字说明的函数,称为常成员函数。关键字说明的函数,称为常成员函数。说明格式:说明格式:函数原型声明时,函数类型函数原型声明时,函数类型 函数名函数名(参数表参数表)const函数定义时,函数类型函数定义时,函数类型 函数名函数名(参数表参数表)const /*函数函数体体*/注意事项注意事项:const是函数类型的一部分,在实现时也要带关键字是函数类型的一部分,在实现时也要带关键字const 常成员函数不能更新对象的数据成员,也不能调用该类中的常成员函数不能更新对象的数据成员,也不能调用该类中的非非const成员函数成员函数 常对象只能调用它的常成员函数,而不能调用其他成员函数常对象只能调用它的常成员函数,而不能调用其他成员函数 const关键字可以被用于参与函数重载的区分关键字可以被用于参与函数重载的区分举例:举例:S5_6用const修饰的对象成员p 常数据成员常数据成员使用使用const说明的数据成员称为常数据成员。说明的数据成员称为常数据成员。常数据成员的初始化方式:构造函数对常数据成员的常数据成员的初始化方式:构造函数对常数据成员的初始化,只能通过初始化列表。初始化,只能通过初始化列表。举例:举例:S5_7C+程序的组织pC+源程序的构成源程序的构成类的声明类的声明;类的成员函数的实现类的成员函数的实现;主函数。主函数。pC+源程序的组织一多文件结构源程序的组织一多文件结构类的定义文件类的定义文件(*.h文件文件);类的实现文件类的实现文件(*.cpp文件文件);类的使用文件类的使用文件(*.cpp主函数文件主函数文件)。p多文件结构的优点多文件结构的优点可以对不同的文件进行单独编写、编译,最后在连接可以对不同的文件进行单独编写、编译,最后在连接;在程序调试时、修改时只对一个类的定义和实现进行操作,而其在程序调试时、修改时只对一个类的定义和实现进行操作,而其余部分不用改动。余部分不用改动。(利用类的封装性利用类的封装性)编译预处理程序p#include指令指令-文件包含指令文件包含指令作用作用:将另一个源文件嵌到当前文件该点处将另一个源文件嵌到当前文件该点处.有两种形式有两种形式:#include/在系统默认目录中搜索文件名在系统默认目录中搜索文件名#include“文件名文件名”/先在当前目录中搜索文件名先在当前目录中搜索文件名p#define和和#undef指令指令#define指令用于宏定义指令用于宏定义可以定义符号常量,如可以定义符号常量,如#define Pi 3.1415 /C+用常量代替用常量代替也可以定义带参数的宏,如:也可以定义带参数的宏,如:#define MULTI(x,y)(x)*(y)/C+用内联函数、重载函数和函数模板代替用内联函数、重载函数和函数模板代替p#undef的作用是取消的作用是取消#define定义的宏,使之不再作用定义的宏,使之不再作用编译预处理程序p条件编译指令条件编译指令作用:限定程序中的某些内容要在满足一定条件的情作用:限定程序中的某些内容要在满足一定条件的情况下才参与编译。况下才参与编译。目的:使同一个源程序在不同的编译条件下产生不同目的:使同一个源程序在不同的编译条件下产生不同的目标代码主要用于程序调试和避免文件的重复包含。的目标代码主要用于程序调试和避免文件的重复包含。p一般形式一般形式:五种五种形式形式1:#if 常量表达式常量表达式 程序段程序段;/当当“常量表达式为非零时编译本程序段常量表达式为非零时编译本程序段#endif编译预处理程序p形式形式2:#if 常量表达式常量表达式 程序段程序段1/当当“常量表达式为非零时编译本程序常量表达式为非零时编译本程序段段#else 程序段程序段2/当当“常量表达式为零时编译本程序段常量表达式为零时编译本程序段#endif编译预处理程序p形式形式3:#if 常量表达式常量表达式1 程序段程序段1 /当当“常量表达式常量表达式1为非零时编译本程序段为非零时编译本程序段#elif 常量表达式常量表达式2 程序段程序段2 /*当当“常量表达式常量表达式1为零,而常量表达式为零,而常量表达式2为非零时编为非零时编 译本程序段译本程序段*/#elif 常量表达式常量表达式n 程序段程序段n /*当当“常量表达式常量表达式1至至n-1为零,为零,Ifu常量表达式常量表达式n为非零时编为非零时编 译该序段译该序段*/#else 程序段程序段n+1/其它情况编译本程序段其它情况编译本程序段#endif编译预处理程序p 形式形式4#ifdef 标识符标识符 /若若“标识符标识符”经经#define定义过,且未定义过,且未 程序段程序段1 /经经#undef取消,则编译程序段取消,则编译程序段1,#else/否则编译程序段否则编译程序段2。程序段程序段2 /如果没有程序段如果没有程序段2,#else可省略可省略#endifp形式形式5#ifndef 标识符标识符程序段程序段1#else程序段程序段2#endif写在最后写在最后成功的基成功的基础在于好的学在于好的学习习惯The foundation of success lies in good habits30谢谢大家荣幸这一路,与你同行ItS An Honor To Walk With You All The Way讲师:XXXXXX XX年XX月XX日
展开阅读全文