第5章数据的共享与保护.ppt
《第5章数据的共享与保护.ppt》由会员分享,可在线阅读,更多相关《第5章数据的共享与保护.ppt(120页珍藏版)》请在三一办公上搜索。
1、第5章 数据的共享与保护,第5章 数据的共享与保护,1、标识符的作用域与可见性2、对象的生存期3、类的静态成员(微视频)4、类的友元5、共享数据的保护(微视频)6、多文件结构和编译预处理命令(微视频)7、综合实例个人银行账户管理程序(微视频)8、小结,第5章 数据的共享与保护,1、标识符的作用域与可见性2、对象的生存期3、类的静态成员(微视频)4、类的友元5、共享数据的保护(微视频)6、多文件结构和编译预处理命令(微视频)7、综合实例个人银行账户管理程序(微视频)8、小结,1、标识符的作用域与可见性,作用域可见性,作用域,作用域是一个标识符在程序正文中有效的区域。C+中标识符的作用域:1、函数
2、原型作用域2、局部作用域(块作用域)3、类作用域4、命名空间作用域(文件作用域),1、函数原型作用域,函数原型中的参数,其作用域始于(,结束于)。例如,设有下列原型声明:double Area(double radius);,2、局部作用域(块作用域),在块中声明的标识符,其作用域自声明处起,限于块中,例如:void fun(int a)int b(a);cinb;if(b0)int c;.,a的作用域在哪儿?,3、类作用域,类作用域作用于特定的成员名。类X的成员m具有类作用域,对m的访问方式如下:如果在X的成员函数中没有声明同名的局部作用域标识符,那么在该函数内可以访问成员m。属于类内访问。
3、通过表达式x.m或者X:m访问。属于类外访问。通过表达式prt-m访问。其中prt为指向X类的一个对象的指针。属于类外访问。,4、命名空间作用域(文件作用域),一个大型的程序通常由不同模块构成,不同的模块甚至有可能是由不同人员开发的。不同模块中的类和函数之间可能发生重名,这样就会引发错误。命名空间(namespace)的概念正是为了解决这个问题而提出的。一个命名空间将不同的标识符集合在一个命名作用域(named scope)内。这样,在不同的命名空间中,即使使用同样的标识符来表示不同的事物,也不会引起命名冲突。,4、命名空间作用域(文件作用域),命名空间的语法形式如下:namespace 命名
4、空间名 命名空间内的各种声明(函数声明、类声明等)在命名空间内部可以直接引用当前命名空间中声明的标识符,如果需要引用其他命名空间的标识符,需要使用以下语法:命名空间名:标识符名,4、命名空间作用域(文件作用域),#include namespace mycode void sqrt();int main()mycode:sqrt();return 0;namespace mycode void sqrt()std:cout sqrt called in the mycode namespace std:endl;,运行结果:sqrt called in the mycode namespace
5、,4、命名空间作用域(文件作用域),在标识符前总使用命名空间限定,会显得过于冗长。C+为此提供了using语句的两种形式:using 命名空间名:标识符名;using namespace 命名空间名;第1种形式将命名空间内的某一指定标识符暴露在当前的作用域内,使得在当前作用域中可以直接引用这个指定的标识符。第2种形式将命名空间内的所有标识符暴露在当前的作用域内,使得在当前作用域中可以直接引用命名空间内的所有(任何)标识符。,4、命名空间作用域(文件作用域),#include namespace mycode void sqrt()std:cout sqrt called in the myco
6、de namespace std:endl;using namespace mycode;int main()sqrt();return 0;,运行结果:sqrt called in the mycode namespace,4、命名空间作用域(文件作用域),C+标准程序库的所有标识符都被声明在std命名空间内,所以:如果前面的程序使用了 using namespace std;那么可以直接使用 cin、cout、endl 等标识符。如果前面的程序没有使用 using namespace std;那么只能这样使用 std:cin、std:cout、std:endl 等标识符。,例5-1 作用域
7、实例,运行结果:i=7j=6i=5,#include using namespace std;int i;/在全局命名空间中的全局变量namespace Ns int j;/在 Ns 命名空间中的全局变量int main()i=5;/为全局变量 i 赋值Ns:j=6;/为全局变量 j 赋值using namespace Ns;/子块int i;/局部变量,局部作用域i=7;/为局部变量 i 赋值cout i=i endl;/输出 7cout j=j endl;/输出 6cout i=i endl;/输出 5return 0;,可见性,可见性是从对标识符的引用的角度来看标识符的有效范围。可见性表
8、示从内层作用域向外层作用域“看”时能看见什么。如果标识符在某处可见,则就可以在该处引用此标识符。,可见性,作用域可见性的一般规则:标识符应声明在先,引用在后。在同一作用域中,不能声明同名的标识符。在没有互相包含关系的不同的作用域中声明的同名标识符,互不影响。如果某个标识符在外层中声明,且在内层中没有同一标识符的声明,则该标识符在内层可见。如果在两个或多个具有包含关系的作用域中声明了同名标识符,则外层标识符在内层不可见。,同一作用域中的同名标识符,在同一作用域内的对象名、函数名、枚举常量名会隐藏同名的类名或枚举类型名。Clock Clock;Clock.setTime();重载的函数可以有相同的
9、函数名。作用域和可见性的原则不仅适用于变量名,而且也同样适用于其他各种标识符,包括常量名、用户自定义的类型名、函数名、枚举类型的取值等。,第5章 数据的共享与保护,1、标识符的作用域与可见性2、对象的生存期3、类的静态成员(微视频)4、类的友元5、共享数据的保护(微视频)6、多文件结构和编译预处理命令(微视频)7、综合实例个人银行账户管理程序(微视频)8、小结,2、对象的生存期,对象(包括简单变量)从产生到结束的这段时间就是它的生存期。在对象生存期内,对象(包括简单变量)将保持它的状态(即:数据成员的值),直到它们被更新为止。对象的生存期分为:静态生存期动态生存期,静态生存期,如果对象生存期与
10、程序的运行期相同,则称它具有静态生存期。在命名空间作用域中声明的对象具有这种静态生存期。在函数内部声明静态生存期对象,要冠以关键字static。,例:静态生存期,运行结果:i=523,#include using namespace std;int i=5;/命名空间作用域,i具有静态生存期void print()static int j=1;/静态局部变量j具有静态生存期 j+;cout j endl;int main()couti=iendl;print();print();return 0;,动态生存期,块作用域中声明的、没有用static修饰的对象是动态生存期的对象(习惯称局部生存期对
11、象)。局部生存期对象诞生于声明点时,结束于声明所在的块执行完毕时。,例:动态生存期,运行结果:i=6,a=2i=6,a=3,#include using namespace std;void fun();int main()fun();fun();return 0;void fun()static int a=1;/a是静态生存期int i=5;/i是动态生存期a+;i+;cout i=i,a=a endl;,例5-2 变量的生存期与可见性,#includeusing namespace std;int i=1;/i 为全局变量,具有静态生存期void other(void)static in
12、t a=2;/a,b 为静态局部变量,具有全局寿命,局部可见,static int b;/只在第一次进入函数时被初始化int c=10;/c 为局部变量,具有动态生存期,每次进入函数时都初始化a+=2;i+=32;c+=5;cout-OTHER-endl;cout i:i a:a b:b c:c endl;b=a;,int main()static int a;/a 为静态局部变量,具有全局寿命,局部可见/b,c 为局部变量,具有动态生存期int b=-10;int c=0;cout-MAIN-endl;cout i:i a:a b:b c:c endl;c+=8;other();cout-M
13、AIN-endl;cout i:i a:a b:b c:c endl;i+=10;other();return 0;,运行结果:-MAIN-i:1 a:0 b:-10 c:0-OTHER-i:33 a:4 b:0 c:15-MAIN-i:33 a:0 b:-10 c:8-OTHER-i:75 a:6 b:4 c:15,例5-2,例5-3,#includeusing namespace std;class Clock/时钟类定义public:/外部接口Clock();void setTime(int NewH,int NewM,int NewS);/3个形参均具有函数原型作用域void show
14、Time();private:/私有数据成员int hour,minute,second;,例5-3具有静态和动态生存期对象的时钟程序,/时钟类成员函数实现Clock:Clock():hour(0),minute(0),second(0)/默认构造函数void Clock:setTime(int NewH,int NewM,int NewS)/3个形参均具有局部作用域hour=NewH;minute=NewM;second=NewS;void Clock:showTime()cout hour:minute:second endl;,例5-3,Clock globClock;/声明全局对象gl
15、obClock,具有静态生存期,命名空间作用域(文件作用域),由默认构造函数初始化为 0:0:0int main()/主函数cout The first time output:endl;/引用具有命名空间作用域(文件作用域)的对象globClock;对象的成员函数具有类作用域,显示 0:0:0globClock.showTime();globClock.setTime(8,30,30);/将时间设置为 8:30:30Clock myClock(globClock);/声明具有块作用域的对象myClockcout The second time output:endl;myClock.show
16、Time();/引用具有块作用域的对象myClockreturn 0;,运行结果:The first time output:0:0:0The second time output:8:30:30,例5-3,第5章 数据的共享与保护,1、标识符的作用域与可见性2、对象的生存期3、类的静态成员(微视频)4、类的友元5、共享数据的保护(微视频)6、多文件结构和编译预处理命令(微视频)7、综合实例个人银行账户管理程序(微视频)8、小结,3、类的静态成员,在结构化程序设计中,程序模块的基本单位是函数,因此模块间对内存中数据的共享是通过函数与函数之间的数据共享来实现的,其中包括两个途径参数传递和全局变量
17、。数据存储在局部对象中,通过参数传递实现共享函数间的参数传递。数据存储在全局对象中。,使用全局对象,#includeint global;void f()global=5;void g()cout global endl;int main()f();g();/输出“5”return 0;,将函数与数据封装,#includeusing namespace std;class Application public:void f();void g();private:int global;void Application:f()global=5;void Application:g()coutglo
18、balendl;,int main()Application MyApp;MyApp.f();MyApp.g();return 0;,3、类的静态成员,面向对象的程序设计方法兼顾数据的共享与保护,将数据与操作数据的函数封装在一起,构成集成度更高的模块。类中的数据成员可以被同一类中的任何一个函数访问。这样一方面在类内部的函数之间实现了数据共享,另一方面这种共享是受限制的,可以设置适当的访问控制属性。把共享只限制在类的范围之内,对类外来说,类的数据成员仍然是隐藏的,达到了共享与隐藏。,3、类的静态成员,在数据共享方面,除了:函数之间的数据共享参数传递和全局变量类内部的函数之间实现了数据共享之外,对
19、象与对象之间也需要共享数据。静态成员能解决同一个类的不同对象之间数据和函数共享的问题。,3、类的静态成员,例:class Employee private:int empNo;int id;string name;/字符串对象;如果需要统计雇员总数,这个数据存放在哪里?,3、类的静态成员,例:class Employee Private:int empNo;int id;string name;/字符串对象static int count;count 这个数据成员是静态数据成员,表示总数。,3、类的静态成员,如果以类外的变量来存储总数,则不能实现数据的隐藏。如果在类中增加一个数据成员用于存放总
20、数,必然在每一个对象中都存储一个副本。这样不仅使数据冗余,而且每个对象分别维护一个“总数”,容易形成维护对象的成本太高,并且极易造成数据的不一致。由于这个总数应该是为Employee类的所有对象所共享,因此比较理想的方案是类的所有对象共同拥有一个存放总数的数据成员静态数据成员。,3、类的静态成员,静态数据成员静态成员函数,静态数据成员,count 这个静态数据成员具有“类属性”,表明这个属性不属于任何一个具体对象,而是为整个类所共有,或者说,为每个对象所共有。静态成员在每个类只有一个副本,而不是在每一个对象中都存储一个副本。静态成员由该类的所有对象共同维护和使用,从而实现了同一类的不同对象之间
21、的数据共享。类属性是描述类的所有对象共同特征的一个数据项,对于任何对象实例,它的属性值是相同的。,静态数据成员,静态数据成员用关键字static声明。该类的所有对象维护该成员的同一个拷贝。必须在类外定义和初始化,用作用域运算符(:)来指明所属的类。静态成员函数类外代码可以使用类名和作用域运算符(:)来调用静态成员函数。静态成员函数只能引用属于该类的静态数据成员或静态成员函数。,例5-4 具有静态数据成员的 Point类,class Point/Point类定义public:/外部接口Point(int xx=0,int yy=0):x(xx),y(yy)/构造函数 count+;/在构造函数中
22、对 count 累加,所有对象共同维护同一个 countPoint(Point,int Point:count=0;/静态数据成员定义和初始化,使用类名限定int main()/主函数Point a(4,5);/定义对象a,其构造函数会使 count 增 1cout Point A:a.getX(),a.getY();a.showCount();/输出对象个数Point b(a);/定义对象b,其复制构造函数会使 count 增 1cout Point B:b.getX(),b.getY();b.showCount();/输出对象个数cout Point A:a.getX(),a.getY()
23、;a.showCount();/输出对象个数cout The size of Point:sizeof(Point)endl;/输出8,而不是12return 0;,运行结果:Point A:4,5 Object count=1Point B:4,5 Object count=2Point A:4,5 Object count=2The size of Point:8,例5-4,静态数据成员,在前面的例子中,类Point的数据成员count被声明为静态(static),用来给Point类的对象计数,每定义一个新对象,count的值就相应加1。静态数据成员count的定义和初始化在类外进行,首先
24、要利用类名来引用(int Point:count=0;),其次,虽然这个静态数据成员是私有类型,在这里却可以直接初始化。除此之外,在类外就不允许直接访问了。在所有对象声明之前count的值是初始值0。如何输出这个初始值呢?,静态成员函数,类的静态成员函数是专门用来输出静态成员的。要输出静态成员,可以通过类的某个对象来调用静态成员函数,更可以(更推荐)通过类名来调用静态成员函数。而非静态成员函数只能通过对象名来调用。然而,通过静态成员函数访问非静态成员是相当麻烦的。通常,静态成员函数只用来访问同一个类中的静态数据成员,维护对象之间共享的数据。,例5-5 具有静态数据和函数成员的 Point类,c
25、lass Point/Point类定义public:/外部接口Point(int xx=0,int yy=0):x(xx),y(yy)/构造函数 count+;/在构造函数中对 count 累加,所有对象共同维护同一个 countPoint(Point,int Point:count=0;/静态数据成员定义和初始化,使用类名限定int main()/主函数Point:showCount();/输出对象个数Point a(4,5);/定义对象a,其构造函数会使 count 增 1cout Point A:a.getX(),a.getY();Point:showCount();/输出对象个数Poi
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 数据 共享 保护
链接地址:https://www.31ppt.com/p-5636916.html