




版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
1、C+ Programming Language Dr. Zheng XiaojuanAssociate ProfessorSoftware College of Northeast Normal UniversityOctober. 20081第五章 程序结构 2本 章 内 容 作用域与可见性生存期 局部对象和全局对象 静态成员 友元 常类型编译预处理 3类本身可被定义在三种作用域内:1. 全局作用域。全局类,绝大多数的C+类是定义在该作用域中,我们在前面定义的所有类都是在全局作用域中。2. 在另一个类的作用域中。嵌套类,即一个类包含在另一个类中。3. 在一个块的局部作用域中。局部类,该类完全
2、被块包含。1 作用域与可见性 42 生存期 2.1 静态生存期 1.定义:与程序的运行期相同。静态生存期的变量程序开始运行就存在,直到程序运行结束生存期结束。具有文件作用域的变量具有静态生存期。 2.语法声明:static 。 例如,static int k; 3.分配空间:在固定的数据区域内分配空间。 4.初始化:如果具有静态生存期的变量未初始化,则自动初始化为0。 5.静态变量种类:全局变量、静态局部变量。5运行时的存储空间结构目标代码空间寄存器空间静态区空间堆区空间栈区空间最大地址最小地址6 2.2 局部生存期 1.定义:在块作用域中声明的变量具有局部生存期。此生存期诞生于声明点,而终止
3、于其作用域的结束处。 2.局部变量种类:具有局部生存期的变量,具有块作用域。 块作用域内静态变量,具有静态生存期。 例如: void main( ) static int k; /. 7 2.3 动态生存期 定义:由程序中特定的函数 (malloc( )和free( ) 调用或由操作符(new和delete)创建和释放。具有动态生存期的变量在内存的堆区分配空间。8#includeclass Clock private:int Hour,Minute,Second;public:Clock( ) Hour=0;Minute=0;Second=0;3 局部对象和全局对象9void SetTime(
4、int NewH,int NewM,int NewS);void ShowTime( );Clock( );void Clock:SetTime(int NewH,int NewM,int NewS) Hour=NewH;Minute=NewM;Second=NewS;void Clock:ShowTime( )coutHour:Minute:Secondendl;10Clock globClock; void main( ) coutFirst time output:endl;globClock.ShowTime( );globClock.SetTime(10,30,45);Clock m
5、yclock(globClock); coutSecond time output:endl;myclock.ShowTime( );程序运行结果为First time output:0:0:0Second time output:10:30:4511#includeusing namespace std;int i; /文件作用域int main() i=5; int i; /块作用域 i=7; couti=iendl; /输出7 couti=i; /输出5 return 0;作用域与可见性例12#includeusing namespace std;int i=5; /文件作用域int m
6、ain() couti=iendl; return 0;i具有静态生存期对象的生存期例13#includeusing namespace std;void fun();int main() fun(); fun();void fun() static int a=1; int i=5; a+; i+; couti=i,a=aendl;运行结果:i=6, a=2i=6, a=3i是动态生存期a是静态生存期对象的生存期例14#includeusing namespace std;int i=1; / i 为全局变量,具有静态生存期。int main() static int a; / 静态局部变量
7、,有全局寿命,局部可见。 int b=-10; / b, c为局部变量,具有动态生存期。 int c=0; void other(void); cout-MAIN-n; cout i: i a: a b: b c: cendl; c=c+8; other(); cout-MAIN-n; cout i: i a: a b: b c: cendl; i=i+10; other(); 对象的生存期例15void other(void) static int a=2; static int b; / a,b为静态局部变量,具有全局寿命,局部可见。 /只第一次进入函数时被初始化。 int c=10; /
8、 C为局部变量,具有动态生存期, /每次进入函数时都初始化。 a=a+2; i=i+32; c=c+5; cout-OTHER-n; cout i: i a: a b: b c: cendl; b=a;1716void Render (Image &image)class ColorTable public:ColorTable(void) /* . */ AddEntry(int r, int g, int b) /* . */ /.; ColorTable colors;/. ColorTable ct; / 非法,没有定义ColorTable类!17静态数据成员用关键字static声明该
9、类的所有对象维护该成员的同一个拷贝必须在类外定义和初始化,用(:)来指明所属的类。静态成员函数类外代码可以使用类名和作用域操作符来调用静态成员函数。静态成员函数只能引用属于该类的静态数据成员或静态成员函数。 4 静态成员 18 4.1 静态数据成员 类的普通数据成员: 类的静态数据成员:在类的每一个对象中都拥有一个拷贝,每个对象的同名数据成员可以分别存储不同的数值,这也是每个对象拥有自身特征的保证。是类的数据成员的一种特例。每个类只有一个静态数据成员拷贝,它由该类的所有对象共同维护和使用,从而实现了同一个类的不同对象之间的数据共享。静态数据成员具有静态生存期。19 2.应用要点: (1) 声明
10、:加static关键字说明。 例如:static int n (2) 初始化:在定义时初始化,且必须在类和所有的成员函数之外,与全局变量初始化的方法一样。不能在构造函数中初始化。因为静态数据成员在构造函数被调用之前就已经存在了。形式: := 例如:int point:n=0; (3)引用:静态数据成员属于类,而不属于任何一个对象,所以,在类外通过类名对它进行引用。一般形式如下: :;20 (4) 静态数据成员访问控制限制: private/protected:只能在类内通过公有的静态成员函数访问,在类外无法引用。 public:可以采用“类名:成员名”或“对象名.成员名”访问。21【例4】 含
11、有静态数据成员。#includeclass Test private: int k; public: static int n; Test(int kk)k=kk;n+; void Display( ) coutn=n k=kendl;n为公有静态数据成员,用来给Test类的对象计数,每声明一个新对象,n的值就相应加l。22int Test:n=0; /静态数据成员初始化void main( )Test t1(10);t1.Display( );Test t2(20);t2.Display( );Test:n+;(t1.n+或t2.n+)t2.Display( );三次调用均访问的是t1和t2
12、共同维护的该静态成员的拷贝,这样实现了在t1和t2两个对象间数据共享。程序运行结果为:n=1 k=10n=2 k=20n=3 k=20引用方法23练习:如果我们保持程序的其它部分不变,只将主函数中改为void main( )Test t1(10),t2(20); t1.Display( ); t2.Display( );Test:n+;t2.Display( );程序运行结果?24 4.2 静态函数成员 1.定义:使用static关键字声明的函数成员。同静态数据成员一样,静态函数成员也属于整个类,由同一个类的所有对象共同维护,为这些对象所共享。 2.静态成员函数如何访问成员数据:静态的成员函数
13、没有this指针 (1)访问静态成员数据,可以直接使用其变量名来访问; (2)访问非静态成员数据,需要使用“对象名.成员名”; 3.公有的、静态的成员函数在类外的调用方式:类名:成员函数名(实参表)4.允许用对象调用静态的成员函数。 25【例5】 使用静态函数成员。#include class Mpublic: M(int a)A=a;B+=a; static void f1(M m); private: int A; static int B;void M:f1(M m)cout“A=“m.Aendl; cout“B=“Bendl;int M:B=0;void main() M P(5),Q
14、(10); M:f1(P); M:f1(Q);访问静态成员数据,可以直接使用其变量名,访问非静态成员数据,需要使用“对象名.成员名”;结果:A=5 B=15 A=10 B=1526#includeclass A private: int x; public: static void f(A a);void A:f(A a) coutx;/对x的引用是错误的 couta.x;/正确27【课堂练习】 阅读程序,写出程序运行结果#includeclass pointprivate:int x,y;static int countP; public:point(int xx=0,int yy=0) x
15、=xx;y=yy;countP+; point(point &p); int get_x( ) return x;int get_y( ) return y;static void get_c( ) coutObject id=countPendl;point:point(point &p)x=p.x;y=p.y;countP+;int point:countP=0; void main( )point:get_c( ); /利用类名引用静态函数成员point a(4,5);coutpoint a,a.get_x( ),a.get_y( );a.get_c( );/利用对象名引用静态函数成员p
16、oint b(a);coutpoint b,b.get_x( ),b.get_y( );point:get_c( );/利用类名引用静态函数成员28程序运行结果为: Object id=0 point a,4,5 Object id=1 point b,4,5 Object id=229 5 友元 1.含义:类的体内以friend加以限定的非成员函数,从而可以在此函数体内利用对象访问类中private成员。2.为什么需要友元:(1)在封装和快速性方面合理选择-类的主要特点是使实现数据隐藏,既不允许非成员函数对它访问,但在某些场合下,非成员函数体中需要通过对象名访问private成员,这可以通过
17、友元函数来实现。(2)有些函数需要放在外面或者类设计完后补充的,而不能成为成员函数,但是又需要访问类中的私有成员。3.作用:实现直接访问数据。30 5.1 友元函数 1.定义:如果友元是普通函数或类的成员函数,则称为友元函数。友元函数是在类声明中由关键字friend修饰的非成员函数。 2.语法: (1)普通函数声明为友元函数的形式: friend (参数表) (2)成员函数声明为友元函数的形式: friend :(参数表)31 3. 应用要点: (1)友元函数的声明可以在类声明中的任何位置,既可在public区,也可在protected区,意义完全一样。 (2)友元函数的定义一般放在类的外部,
18、最好与类的其它成员函数定义放在一起。如果是普通函数作为友元,也可以放在类中。 (3)友元函数不是本类的成员函数,但是它可以通过对象名访问类的所有成员,包括私有和保护成员。 (4)要慎用友元。32【例】 普通函数作友元函数。#include#includeclass pointprivate:double x,y; public: point(double xx=0,double yy=0) x=xx;y=yy; double get_x( ) return x; double get_y( ) return y; friend double distance(point &p1,point &
19、p2);/普通函数作point的友元;33double distance(point &p1,point &p2)return(sqrt(p1.x-p2.x)*(p1.x-p2.x)+(p1.y-p2.y)*(p1.y-p2.y);void main( ) point myp1(1,1),myp2(4,5);coutThe distance is:distance(myp1,myp2)endl;34 【例】 成员函数作友元函数。#include#includeclass point;/前向声明point类class A public:double distance(point &p1,poin
20、t &p2);/.;class point private:double x,y;35public:point(double xx=0,double yy=0) x=xx;y=yy;double get_x( ) return x;double get_y( ) return y;friend double A:distance(point &p1,point &p2); /A类的成员函数作point的友元; double A:distance(point &p1,point &p2)return(sqrt(p1.x-p2.x)*(p1.x-p2.x)+(p1.y-p2.y)*(p1.y-p2
21、.y);36void main( )point myp1(1,1),myp2(4,5); A obj;/声明一个A类的对象coutThe distance is:obj.distance(myp1,myp2)endl; 在主函数中一定要声明一个A类的对象。只有这样,才能通过对象名调用友元函数。374.普通函数作友元函数与成员函数对比: (1)定义:原型定义-采用friend加以限定; 函数体定义-不必采用“类名:”加以限定。 (2)调用方面:友元函数可直接调用,不必采用对象方式调用。5.普通函数作友元函数与一般函数对比: (1)定义:需要在类中加以原型说明(注册为友好成员) (2)编程应用:友
22、元函数体内可以访问类中的私有成员。 成元函数 友元函数 一般函数 “准成员函数” 安全性-方便性 折中38 5.2 友元类 1.如果友元是一个类,则称为友元类。 2.语法声明形式: friend class 3.应用要点: (1)友元类的声明同样可以在类声明中的任何位置。 (2)友元类的所有成员函数都成为友元函数。 例如,若A类为B类的友元类,则A类的所有成员函数都是B类的友元函数,都可以访问B类的私有和保护成员。39用友元类的方法重做例8。#include#includeclass point;/前向声明point类class Apublic:double distance(point &p
23、1,point &p2);/.;class point40private:double x,y;public:point(double xx=0,double yy=0) x=xx;y=yy;double get_x( ) return x;double get_y( ) return y;friend class A;/A类为友元类;double A:distance(point &p1,point &p2)return (sqrt(p1.x-p2.x)*(p1.x-p2.x)+(p1.y-p2.y)*(p1.y-p2.y); 41 void main( ) point myp1(1,1),
24、myp2(4,5);A obj;/必须声明一个A类的对象coutThe distance is:“ obj.distance(myp1,myp2)endl; 友元类的成员函数可以通过对象名直接访问到隐藏的数据,达到高效协调工作的目的。42 4.两点注意: 友元关系是不能传递的。B类是A类的友元,C类是B类的友元,C类和A类之间如果没有声明,就没有任何友元关系,不能进行数据共享。 友无关系是单向的。如果声明B类是A类的友元,B类的成员函数就可以访问A类的私有和保护数据,但A类的成员函数却不能访问B类的私有和保护数据。431.功能:类型修饰符,左结合。用来冻结一个变量的值,使其值在程序中不能被进一
25、步改变(置成只读属性,即变为常量)。2.定义:const 类型定义符 变量名=初值; (当T是一个简单数据类型时 T const=const T)例如:const int sumValue=10; (或int const sumValue=10;)3.应用要点: (1)替代C中的预处理命令#define,但比它更加语义精确,因为#define无法反映常量的数据类型。 如:#define sumValue=10 /此时的sumValue是char型还是int型 6 常类型(const)44(2)对变量经const修饰后,必须给变量赋初值(但函数的形参不需赋初值),一经const修饰后便不能修改此
26、变量之值 const int sumValue=10; sumValue=0; /错误void Display(const int *a,int n) couta0; /=*(a+0),显示数组中的第一个元素之值a0=1; /错误,不能修改其值(不能通过指针来改变目标单元之值)45()区分修饰指针的两种不同用法:a)指向常对象的指针变量: const int *p=&X;此时不能通过指针来改变目标单元之值,即*p=1是错误的,但是p本身可以被改变p=&Y;此种用法常用于函数的形参void fun (const int *ptr) b)常指针:int *const p=&X; 此时p本身不可以被
27、改变(p=&Y是错误的);但p所指向的目标的单元之值是可以被改变的(如*p=2;即x=2);此时p类似于数组名(常量指针)int p10; p0=2. const int *p int *const p=&X;46()C+视const修饰的符号名为常量特性,因而它可以用于任何可能出现数字常量的场合(如数组的大小的说明等). const int ArraySize=10; char arrayArraySize;()由于C+视const修饰的符号名为常量特性,因而并不对它实际分配内存空间const int sumValue=10;/不实际分配内存空间 int sumValue=10; /实际分配
28、内存空间(两个字节)()#define所定义的符号名为全局性常量,因而在整个程序中应保持唯一性;而const可以说明一个局部或全局性同名常量(据此可以改变const符号名之值) 47#define Min 1const int Max=100void main(void)#define Min 2/错误,不能再定义同名常量 const int Max=200/可以再定义同名局部常量487.1 常引用定义:使用const关键字声明的引用称为常引用。常引用所引用的对象不能被更新。语法:常引用的声明形式: const &3. 适用场合: 当函数的参数是指针或引用类型,而该函数又不更新这些参数所标识的
29、对象时,这个参数应该使用const进行声明. C+中经常用指针和常引用做函数参数,这样既能保证数据安全,使数据不能被随意修改,在调用函数时又不必建立实参的拷贝。49【例9】 常引用。#includevoid main( )int n=5;const int &m;/声明m为常引用m=10;coutm=mendl;这段程序编译时有两个错误:error C2530: m : references must be initializederror C2166: l-value specifies const object50将上述程序稍作修改,#includevoid main( )int n=5;
30、const int &m=n;/声明m为常引用coutm=mendl;这时,程序运行结果为m=551【例10】 常引用作形参。#includevoid display(const double &r);/常引用作形参void main( )double d(6.5); display(d);void display(const double &r)coutr=rendl; endl;r=5; error C2166: l-value specifies const object常引用做形参时,函数不能更新r所引用的对象,因此,对应的实参就不会被破坏。52 7.2 常对象 定义:使用const关
31、键字声明的对象称为常对象。语法:常对象的声明形式: const 或 const 声明常对象的同时,也要进行初始化,而且该对象以后不能再被更新。 class A private: int x,y;53 public: A(int i=0,int j=0) x=i;y=j; /. ; A cobj1; A const cobj2(3,4); cobj1.print(); cobj2.print();X /. error C2662: print : cannot convert this pointer from const class A to class A & 语法规定不能通过常对象调用普通
32、的成员函数。547.3 常成员函数 定义:使用const关键字声明的函数称为常成员函数。语法:常成员函数声明的形式如下: (参数表) const; 3目的:const成员函数表示该成员函数只能读类数据成员,而不能修改类成员数据。即在不改变对象的成员函数的函数原型中加上const说明。可提高程序的可读性。还能提高程序的可靠性,已定义成const的成员函数,一旦企图修改数据成员的值,则编译器按错误处理。 4应用要点: const是加在函数声明后面的类型修饰符,它是函数类型的一个组成部分,因此,在实现部分也要带const关键字。如果将const放在函数声明前意味着函数的返回值是常量,意义完全不同。
33、55 const关键字可以被用于对重载函数的区分。例如,可以在类中这样声明: void fun( ); void fun( ) const; 常成员函数不能更新对象的数据成员,也不能调用该类中没有用const修饰的成员函数。 如果将一个对象说明为常对象,则通过该对象只能调用它的常成员函数,而不能调用其它成员函数。 在C+中,const对象只能调用const成员函数56【例11】 常成员函数。#includeclass Aprivate:int x,y; public:A(int i=0,int j=0) x=i;y=j;void fun( )/成员函数 cout成员函数: x=x, y=yen
34、dl;void fun( )const /常成员函数cout常成员函数:x=x, y=yendl;57void main( )A obj1(1,2);obj1.fun( );const A obj2(3,4);/A类常对象obj2.fun( );通过对象obi1调用的是一般的成员函数,而通过对象obj2调用的是用const修饰的常成员函数。程序运行结果为成员函数: x=1, y=2常成员函数:x=3, y=458 7.4 常数据成员 1.定义:使用关键字const说明的数据成员。包括常引用、常对象等,常数据成员不能被更新. 2.初始化:用成员初始化列表的方式通过构造函数对该数据成员进行初始化。
35、59【例12】 常数据成员。#includeclass Aprivate:const int x;/常数据成员static const int y;/静态常数据成员public:const int &r; /常引用本程序有三个常数据成员60 A(int i):x(i),r(x) /常数据成员通过初始化列表获得初值void fun( )coutx=x, y=y, r=rendl;const int A:y=5;/静态常数据成员的初始化void main( )A obj1(1),obj2(2);obj1.fun( );obj2.fun( );程序运行结果为: x=1, y=5, r=1x=2, y=5, r=261 编 译 预 处 理 1.定义:预处理程序又称为预处理器,它包含在编译器中。预处理程序提供了一组编译预处理指令和预处理操作符。编译器在对源程
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 三角形几何训练试题
- 2025年建国70周年女性发展心得体会
- 2025-2030中国多功能电饭煲行业市场深度分析及前景趋势与投资研究报告
- 2025-2030中国夏凉被行业市场发展分析及发展趋势与投资战略研究报告
- 2025-2030中国城市绿化行业市场深度调研及竞争格局与投资发展潜力研究报告
- 2025-2030中国商用汽车车轮行业市场发展趋势与前景展望战略研究报告
- 人教版《生命.生态.安全》主题班会活动计划
- 2025-2030中国同轴电缆行业市场深度调研及市场策略与投资研究报告
- 2025-2030中国台下冷冻柜行业市场发展趋势与前景展望战略研究报告
- 2025-2030中国可牵引灯塔行业市场发展趋势与前景展望战略研究报告
- 2025年初级社会工作者职业资格考试题库含答案
- T-BSRS 128-2024 核医学放射性废液快速处理技术要求
- 2025年日历表(A4版含农历可编辑)
- (读书笔记)礼物的流动:一个中国村庄中的互惠原则和社会网络
- 《医疗垃圾的分类》课件
- 江苏师范大学成人继续教育网络课程《英语》单元测试及参考答案
- 双碱法脱硫操作规程
- 全国中学生物理竞赛及实验课件
- 病案信息技术基础知识考试重点梳理(最新最全)
- 安全施工作业票(模版)
- 环保管理制度(适用于软件企业)
评论
0/150
提交评论