第三章类和对象的进一步讨论.ppt

上传人:本田雅阁 文档编号:3141670 上传时间:2019-07-16 格式:PPT 页数:109 大小:638.02KB
返回 下载 相关 举报
第三章类和对象的进一步讨论.ppt_第1页
第1页 / 共109页
第三章类和对象的进一步讨论.ppt_第2页
第2页 / 共109页
第三章类和对象的进一步讨论.ppt_第3页
第3页 / 共109页
第三章类和对象的进一步讨论.ppt_第4页
第4页 / 共109页
第三章类和对象的进一步讨论.ppt_第5页
第5页 / 共109页
点击查看更多>>
资源描述

《第三章类和对象的进一步讨论.ppt》由会员分享,可在线阅读,更多相关《第三章类和对象的进一步讨论.ppt(109页珍藏版)》请在三一文库上搜索。

1、第三章 关于类和对象的进一步讨论,构造函数和析构函数是在类体中说明的两种特殊的成员函数。,构造函数是在创建对象时,使用给定的值来将对象初始化。,析构函数的功能正好相反,是在系统释放对象前,对对象做一些善后工作。,构造函数是类的成员函数,系统约定构造函数名必须与类名相同。构造函数提供了初始化对象的一种简单的方法。 构造函数自动执行。,构造函数可以带参数、可以重载,同时没有返回值。构造函数不具有任何类型,不要用void说明。,例3.1 70页Time类的构造函数Time class Time private: int hour,mimute,sec; public: Time() hour=0;

2、minute=0; sec=0; /构造函数,初始化对象 void set_time(); /函数声明 void show_time(); ;,对构造函数,说明以下几点: 1.构造函数的函数名必须与类名相同。构造函数的主要作用是完成初始化对象的数据成员以及其它的初始化工作。 2. 在定义构造函数时,不能指定函数返回值的类型,也不能指定为void类型。 3. 一个类可以定义若干个构造函数。当定义多个构造函数时,必须满足函数重载的原则。,4.构造函数可以指定参数的缺省值。,5.若定义的类要说明(产生,建立)该类的对象时,构造函数必须是公有的成员函数。如果定义的类仅用于派生其它类 (不直接产生该类型

3、的对象)时,则可将构造函数定义为保护的成员函数。 6.构造函数不需用户调用,也不能被用户调用,是系统自动调用的。 例如: t1.Time(); /非法,7. 如果用户没有定义构造函数,系统会自动生成一个构造函数。 由于构造函数属于类的成员函数,它对私有数据成员、保护的数据成员和公有的数据成员均能进行初始化。,class A float x,y; public: A(float a,float b) x=a; y=b;/构造函数,初始化对象 float Sum(void) return x+y; void Set(float a,float b) x=a; y=b; Print(void) co

4、ut“x=“xt“y=“yendl; ; void main(void) A a1(2.0, 3.0);/定义时调用构造函数初始化 A a2(1.0,2.0); a2.Set(10.0, 20.0); /利用成员函数重新为对象赋值 a1.Print(); a2.Print(); ,例子3.2 72页 长方柱Box类的构造函数 class Box int height,width,length; public: Box(int,int,int); /声明带参数的构造函数 int volume() return (height*width*length; ; Box:Box(int h, int

5、w, int len) height=h; width=w; length=len; ,class A float x,y; public: A(float a, float b=10) x=a; y=b; A() x=0; y=0; void Print(void) coutxtyendl; ; void main(void) A a1, a2(20.0), a3(3.0, 7.0); a1.Print(); a2.Print(); a3.Print(); ,0 0 20 10 3 7,带缺省参数的构造函数,不带参数的构造函数,每一个对象必须要有相应的构造函数,每一个对象必须要有相应的构造函

6、数,若没有显式定义构造函数,系统默认缺省的构造函数。,class A float x,y; public: A() void Print(void) coutxtyendl; ;,隐含的缺省的构造函数,A a1, a2;,只允许这样定义对象,对象开辟了空间,但没有初始化,对局部对象,静态对象,全局对象的初始化对于局部对象,每次定义对象时,都要调用构造函数。 对于静态对象,是在首次定义对象时,调用构造函数的,且由于对象一直存在,只调用一次构造函数。 对于全局对象,是在main函数执行之前调用构造函数的。,class A int x,y; public: A(int a) x=a; cout“1n

7、”; A(int a, int b) x=a,y=b;cout“2n”; ; A a1(3); void f(void) A b(2,3); void main(void) A a2(4,5); f(); f(); ,1,2,2,2,class A float x,y; public: A(float a, float b)x=a;y=b;cout“初始化自动局部对象n“; A() x=0; y=0; cout“初始化静态局部对象n“; A(float a) x=a; y=0; cout“初始化全局对象n“; void Print(void) coutxtyendl; ; A a0(100.0

8、);/定义全局对象 void f(void) cout“ 进入f()函数n“;A a2(1,2); static A a3; /初始化局部静态对象 void main(void) cout“进入main函数n“; A a1(3.0, 7.0);/定义局部自动对象 f(); f(); ,初始化全局对象,进入main函数,初始化自动局部对象,进入f()函数,初始化局部静态变量,进入f()函数,初始化自动局部对象,初始化自动局部对象,缺省的构造函数,在定义类时,若没有定义类的构造函数,则编译器自动产生一个缺省的构造函数,其格式为: className:className() 缺省的构造函数并不对所产

9、生对象的数据成员赋初值;即新产生对象的数据成员的值是不确定的。,class A float x,y; public: A() /缺省的构造函数,编译器自动产生,可以不写 float Sum(void) return x+y; void Set(float a,float b) x=a; y=b; void Print(void) cout“x=“xt“y=“yendl; ; void main(void) A a1,a2;/产生对象时,自动调用缺省的构造函数,不赋值 a1.Set (2.0,4.0); cout“a1: “; a1.Print (); cout“a1.sum=“a1.Sum (

10、)endl; a2.Print();/打印随机值 ,关于缺省的构造函数,说明以下几点: 1、在定义类时,只要显式定义了一个类的构造函数,则编译器就不产生缺省的构造函数,2、所有的对象在定义时,必须调用构造函数,不存在没有构造函数的对象!,class A float x,y; public: A(float a,float b) x=a; y=b; void Print(void) coutxtyendl; ; void main(void) A a1; A a2(3.0,30.0); ,显式定义了构造函数,不产生缺省的构造函数,error,定义时,没有构造函数可供调用,3、在类中,若定义了没有

11、参数的构造函数,或各参数均有缺省值的构造函数也称为缺省的构造函数,缺省的构造函数只能有一个。,4、产生对象时,系统必定要调用构造函数。所以任一对象的构造函数必须唯一。,class A float x,y; public: A(float a=10,float b=20) x=a; y=b; A() void Print(void) coutxtyendl; ; void main(void) A a1; A a2(3.0,30.0); ,两个函数均为缺省的构造函数,两个构造函数均可供调用,构造函数不唯一,用参数初始化表对数据成员初始化:,Box:Box(int h, int w, int le

12、n) height=h; width=w; length=len; 等同与下面的程序: Box:Box(int h, int w, int len):height(h), width(w), length(len) 即在原来函数”)”后加一个冒号”:”,然后列出参数的初始化表。,析构函数,析构函数的作用与构造函数正好相反,是在对象的生命期结束时,释放系统为对象所分配的空间,即要撤消一个对象。,析构函数也是类的成员函数,定义析构函数的格式为: ClassName:ClassName( ) / 函数体; ,析构 函数的特点如下: 1、析构函数是成员函数,函数体可写在类体内,也可写在类体外。,2、析

13、构函数是一个特殊的成员函数,函数名必须与类名相同,并在其前面加上字符“”,以便和构造函数名相区别。,3、析构函数不能带有任何参数,不能有返回值,不指定函数类型。,在程序的执行过程中,当遇到某一对象的生存期结束时,系统自动调用析构函数,然后再收回为对象分配的存储空间。,4、一个类中,只能定义一个析构函数,析构函数不允许重载。,5、析构函数是在撤消对象时由系统自动调用的。,class A float x,y; public: A(float a,float b) x=a;y=b;cout“调用非缺省的构造函数n“; A() x=0; y=0; cout“调用缺省的构造函数n“ ; A() cout

14、“调用析构函数n“; void Print(void) coutxtyendl; ; void main(void) A a1; A a2(3.0,30.0); cout“退出主函数n“; ,调用缺省的构造函数,调用非缺省的构造函数,退出主函数,调用析构函数,调用析构函数,例子3.5 7880页 student类 class Student Student() /定义析构函数 cout“Destructor called.”endl; ; 析构次序与构造次序相反。 见80页的执行结果。 80页图3.1,构造函数与new运算符,可以使用new运算符来动态地建立对象。建立时要自动调用构造函数,以便

15、完成初始化对象的数据成员。最后返回这个动态对象的起始地址。,用new运算符产生的动态对象,在不再使用这种对象时,必须用delete运算符来释放对象所占用的存储空间。,用new建立类的对象时,可以使用参数初始化动态空间。,class A float x,y; public: A(float a, float b) x=a;y=b; A() x=0; y=0; void Print(void) coutPrint(); pa2-Print(); delete pa1; /用delete释放空间 delete pa2; /用delete释放空间 ,5 0 0,在程序的执行过程中,对象如果用new运算

16、符开辟了空间,则在类中应该定义一个析构函数,并在析构函数中使用delete删除由new分配的内存空间。因为在撤消对象时,系统自动收回为对象所分配的存储空间,而不能自动收回由new分配的动态存储空间。,class Str char *Sp; int Length; public: Str(char *string) if(string) Length=strlen(string); Sp=new charLength+1; strcpy(Sp,string); else Sp=0; void Show(void) coutSpendl; Str() if(Sp) delete Sp; ; voi

17、d main(void) Str s1(“Study C+“); s1.Show(); ,在构造函数中将成员数据指针指向动态开辟的内存,用初值为开辟的内存赋值,析构函数,当释放对象时收回用new开辟的空间,string,Length=strlen(string);,Sp=new charLength+1;,Sp,new开辟的空间,strcpy(Sp,string);,用new运算符为对象分配动态存储空间时,调用了构造函数,用delete删除这个空间时,调用了析构函数。当使用运算符delete删除一个由new动态产生的对象时,它首先调用该对象的析构函数,然后再释放这个对象占用的内存空间。,可以用

18、new运算符为对象分配存储空间,如:,A *p; p=new A;,这时必须用delete才能释放这一空间。,delete p;,class A float x,y; public: A(float a, float b) x=a; y=b; coutPrint(); delete pa1; /调用析构函数 cout“退出main()函数n“; ,进入main()函数,调用了构造函数,3 5,调用了析构函数,退出main()函数,不同存储类型的对象调用构造函数及析构函数,1、对于全局定义的对象(在函数外定义的对象),在程序开始执行时,调用构造函数;到程序结束时,调用析构函数。,2、对于局部定义

19、的对象(在函数内定义的对象),当程序执行到定义对象的地方时,调用构造函数;在退出对象的作用域时,调用析构函数。,3、用static定义的局部对象,在首次到达对象的定义时调用构造函数;到程序结束时,调用析构函数,4、对于用new运算符动态生成的对象,在产生对象时调用构造函数,只有使用delete运算符来释放对象时,才调用析构函数。若不使用delete来撤消动态生成的对象,程序结束时,对象仍存在,并占用相应的存储空间,即系统不能自动地调用析构函数来撤消动态生成的对象。,class A float x,y; public: A(float a, float b)x=a;y=b;cout“初始化自动局

20、部对象n“; A() x=0; y=0; cout“初始化静态局部对象n“; A(float a) x=a; y=0; cout“初始化全局对象n“; A() cout“调用析构函数”endl; ; A a0(100.0);/定义全局对象 void f(void) cout“ 进入f()函数n“; A ab(10.0, 20.0);/定义局部自动对象 static A a3; /初始化局部静态对象 void main(void) cout“进入main函数n“; f(); f(); ,初始化全局对象,进入main函数,初始化自动局部对象,进入f()函数,初始化静态局部对象,进入f()函数,初始

21、化自动局部对象,调用析构函数,调用析构函数,调用析构函数,调用析构函数,举例:建立一个类NUM,求指定数据范围内的所有素数。 如: 定义类NUM的对象test,查找范围为100200,正确的输出结果: num=21 101 103 107 109 113 127 131 ,动态构造及析构对象数组,用new运算符来动态生成对象数组时,自动调用构造函数,而用delete运算符来释放p1所指向的对象数组占用的存储空间时,在指针变量的前面必须加上 , 才能将数组元素所占用的空间全部释放。否则,只释放第0个元素所占用的空间。,pa1=new A3; . delete pa1;,class A float

22、 x,y; public: A(float a=0, float b=0)x=a; y=b;cout“调用了构造函数n“; void Print(void) coutxtyendl; A() cout“调用了析构函数n“; ; void main(void) cout“进入main()函数n“; A *pa1; pa1=new A3;/开辟数组空间 cout“n完成开辟数组空间nn“; delete pa1; /必须用删除开辟的空间 cout“退出main()函数n“; ,进入main()函数,调用了构造函数,调用了构造函数,调用了构造函数,完成开辟数组空间,调用了析构函数,调用了析构函数,调

23、用了析构函数,退出main()函数,缺省的析构函数,若在类的定义中没有显式地定义析构函数时,则编译器自动地产生一个缺省的析构函数,其格式为: ClassName:ClassName() ;,任何对象都必须有构造函数和析构函数,但在撤消对象时,要释放对象的数据成员用new运算符分配的动态空间时,必须显式地定义析构函数。,实现类型转换的构造函数,同类型的对象可以相互赋值,相当于类中的数据成员相互赋值; 如果直接将数据赋给对象,所赋入的数据需要强制类型转换,这种转换需要调用构造函数。,class A float x,y; public: A(float a,float b) x=a;y=b;cout

24、“调用构造函数n“; A() cout“调用析构函数n“; void Print(void) coutxtyendl; ; void main(void) A a1(1.0, 10.0); a1.Print(); a1=A(3.0 , 30.0); a1.Print(); cout“退出主函数n“; ,调用构造函数,产生临时对象,初始化并赋值后立即释放,1 10,调用构造函数,调用析构函数,3 30,退出主函数,调用析构函数,注意:当构造函数只有一个参数时,可以用= 强制赋值。,class B float x; public: B(float a) x=a; cout“调用构造函数n“; B(

25、) cout“调用析构函数n“; void Print(void) coutxendl; ; void main(void) B b1(1.0) ; b1.Print(); B b2=100; b2.Print(); b1=10; b1.Print(); cout“退出主函数n“; ,调用构造函数,单参数可以这样赋值,1,调用构造函数,100,调用构造函数,调用析构函数,10,退出主函数,调用析构函数,调用析构函数,b1=B(10),产生一个临时对象,完成拷贝功能的构造函数,可以在定义一个对象的时候用另一个对象为其初始化,即构造函数的参数是另一个对象的引用,这种构造函数常为完成拷贝功能的构造函

26、数。,完成拷贝功能的构造函数的一般格式为: ClassName:ClassName(ClassName &) / 函数体完成对应数据成员的赋值 ,class A float x,y; public: A(float a=0, float b=0)x=a; y=b; A(A ;,void main(void) A a1(1.0,2.0); A a2(a1); ,形参必须是同类型对象的引用,实参是同类型的对象,class A float x,y; public: A(float a=0, float b=0)x=a; y=b; cout“调用了构造函数n“; A(A ,调用了构造函数 调用了完成拷

27、贝功能的构造函数 1 2 1 2 调用了析构函数 调用了析构函数,用已有的对象中的数据为新创建的对象赋值,如果没有定义完成拷贝功能的构造函数,编译器自动生成一个隐含的完成拷贝功能的构造函数,依次完成类中对应数据成员的拷贝。,A:A(A ,隐含的构造函数,class A float x,y; public: A(float a=0, float b=0)x=a; y=b; cout“调用了构造函数n“; void Print(void) coutxtyendl; A() cout“调用了析构函数n“; ; void main(void) A a1(1.0,2.0); A a2(a1); A a3

28、=a1;/可以这样赋值 a1.Print(); a2.Print(); a3.Print(); ,调用了构造函数 1 2 1 2 1 2 调用了析构函数 调用了析构函数 调用了析构函数,隐含了拷贝的构造函数,由编译器为每个类产生的这种隐含的完成拷贝功能的构造函数,依次完成类中对应数据成员的拷贝。,但是,当类中的数据成员中使用new运算符,动态地申请存储空间进行赋初值时,必须在类中显式地定义一个完成拷贝功能的构造函数,以便正确实现数据成员的复制。,class Str int Length; char *Sp; public: Str(char *string) if(string)Length=

29、strlen(string); Sp=new charLength+1; strcpy(Sp,string); else Sp=0; void Show(void)coutSpendl; Str() if(Sp) delete Sp; ; void main(void) Str s1(“Study C+“); Str s2(s1); s1.Show (); s2.Show (); ,隐含的拷贝构造函数为: Str:Str(Str ,s1.Sp,s2.Sp,new开辟的空间,同一空间释放两次,造成运行错误。,在这种情况下,必须要定义完成拷贝功能的构造函数。,Str:Str(Str ,s1.Sp,

30、原来s1开辟的空间,s2.Sp,拷贝函数中用new开辟的空间,构造函数与对象成员,对类A的对象初始化的同时还要对其成员数据类B的对象进行初始化,所以,类A的构造函数中要调用类B的构造函数。,class B ;,class A int x , y; B b1,b2; ;,在类A中包含类B的对象,class A float x,y; public: A(int a,int b) x=a;y=b; void Show() cout “x=“xt“y=“yn; ; class C float z; A a1;/类C的数据成员为类A 的对象a1 public: C(int a,int b,int c):

31、a1(b, c) z=a;/类C的对象初始化 void Show()cout “z=“an; a1.Show(); ; void main(void) C c1(1, 2, 3 ); /对类C的对象初始化 c1.Show(); ,在类C中调用类A的成员函数,利用类A的构造函数对类A的对象初始化,a1,A,C,a1(b, c),ClassName:ClassName(args):c1(args1),cn(agrsn) /对其它成员的初始化 初始化对象成员的参数(实参)可以是表达式。,也可以仅对部分对象成员进行初始化。,class A float x,y; public: A(int a,int

32、b) x=a;y=b; void Show() cout “x=“xt“y=“yn; ; class B float x1,y1; public: B(int a, int b) x1=a; y1=b; void Show() cout“x1=“x1t“y=“yn; ; class C float z; A a1; B b1; public: C(int a,int b,int c,int d, int e):a1(a+b, c) ,b1(a,d) z=e; void Show()cout “z=“an; a1.Show();b1.Show(); ; void main(void) C c1(

33、1, 2, 3 ,4,5); /对类C的对象初始化 ,对象初始化的参数可以是表达式,对对象成员的构造函数的调用顺序取决于这些对象成员在类中说明的顺序,与它们在成员初始化列表中的顺序无关。 当建立类ClassName的对象时,先调用各个对象成员的构造函数,初始化相应的对象成员,然后才执行类ClassName的构造函数,初始化类ClassName中的其它成员。析构函数的调用顺序与构造函数正好相反。,class A float x; public: A(int a) x=a; cout“调用了A的构造函数n”; A()cout“调用了A的析构函数n”; ; class B float y; publ

34、ic: B(int a) y=a; cout“调用了B的构造函数n”; B()cout“调用了B的析构函数n”; ; class C float z; B b1; A a1; public: C(int a,int b,int c): a1(a),b1(b)z=c;cout“调用了C的构造函数n”; C()cout“调用了C的析构函数n”; ; void main(void) C c1(1,2,3); ,调用了B的构造函数,调用了A的构造函数,调用了C的构造函数,调用了C的析构函数,调用了A的析构函数,调用了B的析构函数,通常,每当说明一个对象时,把该类中的有关成员数据拷贝到该对象中,即同一类

35、的不同对象,其成员数据之间是互相独立的。,静态成员,class A int x,y; public: void Setxy(int a, int b) x=a; y=b; ; A a1, a2;,a1.x,a1.y,a2.x,a2.y,a1. Setxy(),a2. Setxy(),a1.Setxy(1,2); a2.Setxy(3,4);,this-x=a;,this-y=b;,当我们将类的某一个数据成员的存储类型指定为静态类型时,则由该类所产生的所有对象,其静态成员均共享一个存储空间,这个空间是在编译的时候分配的。换言之,在说明对象时,并不为静态类型的成员分配空间。 在类定义中,用关键字s

36、tatic修饰的数据成员称为静态数据成员。,class A int x,y; static int z; public: void Setxy(int a, int b) x=a; y=b; ; A a1, a2;,z,a1. z,a2. z,不同对象,同一空间,有关静态数据成员的使用,说明以下几点: 1、类的静态数据成员是静态分配存储空间的,而其它成员是动态分配存储空间的(全局变量除外)。当类中没有定义静态数据成员时,在程序执行期间遇到说明类的对象时,才为对象的所有成员依次分配存储空间,这种存储空间的分配是动态的;而当类中定义了静态数据成员时,在编译时,就要为类的静态数据成员分配存储空间。,

37、2、必须在文件作用域中,对静态数据成员作一次且只能作一次定义性说明。因为静态数据成员在定义性说明时已分配了存储空间,所以通过静态数据成员名前加上类名和作用域运算符,可直接引用静态数据成员。在C+中,静态变量缺省的初值为0,所以静态数据成员总有唯一的初值。当然,在对静态数据成员作定义性的说明时,也可以指定一个初值。,class A int i,j; static int x,y;/定义静态成员 public: A(int a=0,int b=0,int c=0, int d=0) i=a;j=b;x=c;y=d; void Show()cout “i=“it“j=“jt; cout “x=“xt

38、“y=“y“n“; ; int A:x=0; /必须对静态成员作一次定义性说明 int A:y=0; void main(void ) A a(2,3,4,5); a.Show(); A b(100,200,300,400); b.Show(); a.Show(); ,a.x 和b.x在内存中占据一个空间 a.y 和b.y在内存中占据一个空间,i=2 j=3 x=4 y=5,i=100 j=200 x=300 y=400,i=2 j=3 x=300 y=400,class A int i,j; public: static int x; public: A(int a=0,int b=0,in

39、t c=0) i=a ; j=b ; x=c; void Show() cout “i=“it“j=“jt; cout “x=“x“n“; ; int A:x=500; /int A:x void main(void ) A a(20,40,10),b(30,50,100); a.Show (); b.Show (); cout “A:x=”A:xn; /可以直接用类名引用 ,在类外重新定义,3、静态数据成员具有全局变量和局部变量的一些特性。静态数据成员与全局变量一样都是静态分配存储空间的,但全局变量在程序中的任何位置都可以访问它,而静态数据成员受到访问权限的约束。必须是public权限时,才

40、可能在类外进行访问。,4、为了保持静态数据成员取值的一致性,通常在构造函数中不给静态数据成员置初值,而是在对静态数据成员的定义性说明时指定初值。,class A int i; static int count; public: A(int a=0) i=a; count+; cout “Number of Objects=“countn; A() count-; cout “Number of Objects=“countn; void Show() cout “i=“in; cout “count=“count“n“; ; int A:count; void main(void ) A a1

41、(100); A b2; a1.Show(); ,Number of Objects=1,Number of Objects=2,Number of Objects=3,i=100 count=3,Number of Objects=2,Number of Objects=1,Number of Objects=0,静态成员函数 可以将类的成员函数定义为静态的成员函数。即使用关键字static来修饰成员函数 。,class A float x, y; public : A( ) static void sum(void) . ;,对静态成员函数的用法说明以下几点: 1、与静态数据成员一样,在类

42、外的程序代码中,通过类名加上作用域操作符,可直接调用静态成员函数。,2、静态成员函数只能直接使用本类的静态数据成员或静态成员函数,但不能直接使用非静态的数据成员 (可以引用使用)。这是因为静态成员函数可被其它程序代码直接调用,所以,它不包含对象地址的this指针。,class Tc private:int A; static int B;/静态数据成员 public:Tc(int a)A=a; B+=a; static void display(Tc c)/Tc的对象为形参 cout“A=“c.A“,B=“Bendl; ; int Tc:B=2; void main(void) Tc a(2)

43、,b(4); Tc:display (a); Tc:display (b); ,非静态成员,用对象名来引用,静态成员,直接引用,直接用类名来调用静态成员函数,A=2,B=8,A=4,B=8,3、静态成员函数的实现部分在类定义之外定义时,其前面不能加修饰词static。这是由于关键字static不是数据类型的组成部分,因此,在类外定义静态成员函数的实现部分时,不能使用这个关键字 4、不能把静态成员函数定义为虚函数。静态成员函数也是在编译时分配存储空间,所以在程序的执行过程中不能提供多态性。 5、可将静态成员函数定义为内联的(inline),其定义方法与非静态成员函数完全相同。,class Tc

44、private:int A; static int B;/静态数据成员 public:Tc(int a)A=a; B+=a; static void display(Tc c);/Tc的对象为形参 ; void Tc:display(Tc c)/不用static修饰 cout“A=“c.A“,B=“Bendl; int Tc:B=2; void main(void) Tc a(2),b(4); Tc:display (a); Tc:display (b); ,函数原型,类外定义,静态变量,在变量声明前面加上关键字static,就使该变量成为静态的。 对于非静态变量,每个类对象都有自己的拷贝;而

45、静态变量对每个类只有一个拷贝,静态变量可被该类的所有对象共享访问。 还有,静态变量即使在它所属于的函数执行完后还是保留他们的值,这意味着:静态变量在整个程序内一直保留着它的值。,静态变量必须在其类体内声明,但不能在类体内初始化,只能在成员函数或类定义之外(类体外)被初始化。 静态变量的声明和初始化,举例 : class SExample public: static int svar; /静态变量声明 int SExample:svar = 0; /静态变量初始化, 在类的成员函数中可以直接访问该类的静态变量而不必使用成员访问操作符: SExample:cout( ) svar = svar+

46、1; cout”Now,The total is :”svar; 但是,在非成员函数中我们必须以以下两种方式之一访问静态变量:,a. 可以使用成员访问操作符: int SExample:svar = 0; int main() SExample s1; s1.svar = 1; b. 因为类静态变量只有一个拷贝,所以不一定要通过对象或指针来访问,访问静态变量的另一种方法是用被类名限定修饰的名字直接访问它: int SExample:svar = 0; int main() SExample:svar = 1; 当不通过类的成员访问操作符访问静态变量时,必须指定类名以及紧跟其后的域操作符“ : ”。,静态函数,静态函数的声明就是在类体中的函数声明前加上关键字static。 因为静态成员在对象创建之前就已经存在了,所以,静态函数只能访问静态变量,不能够访问非静态变量。 静态函数声明举例: class SExample public: static int svar; static void display() /静态函数声明 cout“The static variable is :“svar; ; int SExample:svar=0;,与静态变量同理,也有两种方式访问静态函数。 a. 可以用成员访问操作符点“ . ” 和箭头“ - ”,为一个类对象或指向类对象的指针调用静态

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 其他


经营许可证编号:宁ICP备18001539号-1