05--数据的共享与保护

本章主要讲解函数原型(类、文件)的作用域与块可见性、 对象的生存期、静态成员、友元、 共享数据的保护、多文件结构和工程、编译预处理命令
展开查看详情

1.C++语言程序设计 第五章 数据的共享与保护 信息工程学院 王红平 Email:cugwhp@qq.com 1

2.C++语言程序设计 本章主要内容  作用域与可见性  对象的生存期  静态成员  友元  共享数据的保护  多文件结构和工程  编译预处理命令 2

3.C++语言程序设计 作用域与可见性 函数原形的作用域  函数原型中的参数,其作用域始于 "(",结束于")"。  例如,设有下列原型声明: double Area(double radius); radius 的作用域仅在于此, 不能用于程序正文其它地 方,因而可有可无。 3

4.C++语言程序设计 作用域与可见性 块作用域  在块中声明的标识符,其作用域自声明处 起,限于块中,例如: void fun(int a) { int b(a); cin>>b; b的作用域 if (b>0) { int c; c的作用域 ...... } } 4

5.C++语言程序设计 作用域与可见性 类作用域  类的内部 – 如果在X的成员函数中没有声明同名的局 部作用域标识符,那么在该函数内可以 访问成员M。  类的外部 – 通过表达式x.M或者X::M访问。 – 通过表达式ptr->M 5

6.C++语言程序设计 作用域与可见性 文件作用域  不在前述各个作用域中出现的声明, 具有文件作用域,这样声明的标识符 的作用域开始于声明点,结束于文件 尾。 6

7.C++语言程序设计 作用域与可见性 可见性  可见性表示从内层作用域向外层作用域 “看”时能看见什么。  如果标识在某处可见,则就可以在该处 引用此标识符。 文件作用域 类作用域 块作用域 7

8.C++语言程序设计 作用域与可见性 可见性  标识符应声明在先,引用在后。  如果某个标识符在外层中声明,且在内层中 没有同一标识符的声明,则该标识符在内层 可见。  对于两个嵌套的作用域,如果在内层作用域 内声明了与外层作用域中同名的标识符,则 外层作用域的标识符在内层不可见。 8

9.C++语言程序设计 作用域与可见性 例 5.1 #include<iostream> using namespace std; int i; //文件作用域 int main() { i=5; { int i; //块作用域 i=7; cout<<"i="<<i<<endl; //输出7 } cout<<"i="<<i; //输出5 return 0; } 9

10.C++语言程序设计 对象的生存期 对象从产生到结束的这段时间就是 它的生存期。在对象生存期内,对象将 保持它的值,直到被更新为止。 10

11.C++语言程序设计 对象的生存期 静态生存期  这种生存期与程序的运行期相同。  在文件作用域中声明的对象具有这种 生存期。  在函数内部声明静态生存期对象,要 冠以关键字static 。 11

12.C++语言程序设计 对象的生存期 例 #include<iostream> using namespace std; int i=5; //文件作用域 int main() { cout<<"i="<<i<<endl; return 0; } i具有静态生存期 12

13.C++语言程序设计 对象的生存期 动态生存期  块作用域中声明的,没有用static修 饰的对象是动态生存期的对象(习惯 称局部生存期对象)。  开始于程序执行到声明点时,结束于 命名该标识符的作用域结束处。 13

14.C++语言程序设计 对象的生存期 例 #include<iostream> using namespace std; void fun(); void main() 运行结果: { fun(); i=6, a=2 fun(); } i=6, a=3 void fun() { static int a=1; i是动态生存期 int i=5; a++; a是静态生存期 i++; cout<<"i="<<i<<",a="<<a<<endl; } 14

15.C++语言程序设计 对象的生存期 例5-3具有静态、动态生存期对象的时钟程序 #include<iostream> using namespace std; class Clock //时钟类声明 {public: //外部接口 Clock(); void SetTime(int NewH, int NewM, int NewS); //三个形参均具有函数原型作用域 void ShowTime(); ~Clock(){} private: //私有数据成员 int Hour,Minute,Second; }; 15

16.//时钟类成员函数实现 Clock::Clock() //构造函数 { Hour=0; Minute=0; Second=0; } void Clock::SetTime(int NewH, int NewM, int NewS) { Hour=NewH; Minute=NewM; Second=NewS; } void Clock::ShowTime() { cout<<Hour<<":"<<Minute<<":"<<Second<<endl; } 20

17.Clock globClock; //声明对象globClock, //具有静态生存期,文件作用域 void main() //主函数 { cout<<"First time output:"<<endl; //引用具有文件作用域的对象: globClock.ShowTime(); //对象的成员函数具有类作用域 globClock.SetTime(8,30,30); Clock myClock(globClock); //声明具有块作用域的对象myClock cout<<"Second time output:"<<endl; myClock.ShowTime(); //引用具有块作用域的对象 } 21

18.程序的运行结果为: First time output: 0:0:0 Second time output: 8:30:30 22

19.C++语言程序设计 静态成员  静态数据成员 静态成员 – 用关键字static声明 – 该类的所有对象维护该成员的同一个拷 贝 – 必须在类外定义和初始化,用(::)来指明 所属的类。  静态成员函数 – 类外代码可以使用类名和作用域操作符 来调用静态成员函数。 – 静态成员函数只能引用属于该类的静态 数据成员或静态成员函数。 19

20.C++语言程序设计 例5-4 具有静态数据成员的 Point类 #include <iostream> 静态成员 using namespace std; class Point {public: Point(int xx=0, int yy=0) {X=xx; Y=yy; countP++; } Point(Point &p); int GetX() {return X;} int GetY() {return Y;} void GetC() {cout<<" Object id="<<countP<<endl;} private: int X,Y; static int countP; }; 20

21.Point::Point(Point &p) { X=p.X; Y=p.Y; countP++; } int Point::countP=0; void main() { Point A(4,5); cout<<"Point A,"<<A.GetX()<<","<<A.GetY(); A.GetC(); Point B(A); cout<<"Point B,"<<B.GetX()<<","<<B.GetY(); B.GetC(); } 28

22.C++语言程序设计 静态成员函数举例 #include<iostream> void Application::f() 静态成员 using namespace std; { global=5;} class Application void Application::g() { public: { cout<<global<<endl;} static void f(); static void g(); int main() private: { static int global; Application::f(); }; Application::g(); int Application::global return 0; =0; } 22

23.C++语言程序设计 静态成员函数举例 class A 静态成员 { public: static void f(A a); private: int x; }; void A::f(A a) { cout<<x; //对x的引用是错误的 cout<<a.x; //正确 } 23

24.C++语言程序设计 具有静态数据、函数成员的 Point类 #include <iostream> 静态成员 using namespace std; class Point //Point类声明 {public: //外部接口 Point(int xx=0, int yy=0) {X=xx;Y=yy;countP++;} Point(Point &p); //拷贝构造函数 int GetX() {return X;} int GetY() {return Y;} static void GetC() {cout<<" Object id="<<countP<<endl;} private: //私有数据成员 int X,Y; static int countP; } 24

25.Point::Point(Point &p) { X=p.X; Y=p.Y; countP++; } int Point::countP=0; void main() //主函数实现 { Point A(4,5); //声明对象A cout<<"Point A,"<<A.GetX()<<","<<A.GetY(); A.GetC(); //输出对象号,对象名引用 Point B(A); //声明对象B cout<<"Point B,"<<B.GetX()<<","<<B.GetY(); Point::GetC(); //输出对象号,类名引用 } 32

26.C++语言程序设计 友元 友元是C++提供的一种破坏数据封装 友  和数据隐藏的机制。 元  通过将一个模块声明为另一个模块的 友元,一个模块能够引用到另一个模 块中本是被隐藏的信息。  可以使用友元函数和友元类。  为了确保数据的完整性,及数据封装 与隐藏的原则,建议尽量不使用或少 使用友元。 26

27.C++语言程序设计 友 友元函数  友元函数是在类声明中由关键字friend 修饰说明的非成员函数,在它的函数 元 体中能够通过对象名访问 private 和 protected成员  作用:增加灵活性,使程序员可以在 封装和快速性方面做合理选择。  访问对象中的成员必须通过对象名。 27

28.C++语言程序设计 友 例5-6 使用友元函数计算两点距离 #include <iostream> #include <cmath> using namespace std; 元 class Point //Point类声明 { public: //外部接口 Point(int xx=0, int yy=0) {X=xx;Y=yy;} int GetX() {return X;} int GetY() {return Y;} friend double Distance(Point &a, Point &b); private: //私有数据成员 int X,Y; }; 28

29.double Distance( Point& a, Point& b) { double dx=a.X-b.X; double dy=a.Y-b.Y; return sqrt(dx*dx+dy*dy); } int main() { Point p1(3.0, 5.0), p2(4.0, 6.0); double d=Distance(p1, p2); cout<<"The distance is "<<d<<endl; return 0; } 36