收藏 分享(赏)

C++ 类类型.ppt

上传人:gnk289057 文档编号:9391740 上传时间:2019-08-05 格式:PPT 页数:265 大小:306KB
下载 相关 举报
C++ 类类型.ppt_第1页
第1页 / 共265页
C++ 类类型.ppt_第2页
第2页 / 共265页
C++ 类类型.ppt_第3页
第3页 / 共265页
C++ 类类型.ppt_第4页
第4页 / 共265页
C++ 类类型.ppt_第5页
第5页 / 共265页
点击查看更多>>
资源描述

1、第三章 类 类 型,数据封装,C+语言与C语言最大的不同,在于C+语言增加了面向对象的概念。C+语言允许用户定义新的抽象数据类型。,类类型,将一组数据和对它们的相关操作封装在一起,实现的是面向对象中的核心概念:数据封装;,对象就是类类型的实例。,3.1 类 与 对 象,3.1.1 类的定义 定义用户定义的类型Date ,考虑对该类型数据的操作,可能有: struct Date int d,m,y; void init_date(Date ,函数和数据类型之间没有联系,因此,需要操作一个Date数据时,需要Date类型的参数。 C+语言允许在结构类型定义中,加入函数的定义,这些函数的目的,也是要

2、操作某个结构的变量。,该结构更复杂定义为:struct Date int d,m,y;void init_date(int,int,int); Date add_day(int n); ;,在Date中定义的函数称为成员函数,它们只能被对应的Date类型的变量(此时,称之为对象)以特殊的方式激活。该Date类型在C+语言中称为类类型,是一种抽象数据类型。,对象激活成员函数的方式为: 对象.成员函数(),Date my_birthday;void f( ) Date today;today.init_date(27,5,2002);my_birthday.init_date(12,7,1968)

3、;Date tomorrow=today;tomorrow.add_day(1); ,成员函数可以在类类型定义时给出,也可以在类类型定义时只给出成员函数的声明,在类型定义外再给出函数的定义。,格式为:type 类名:函数名(形参表) ,void Date:init_date(int dd,int mm,int yy) d=dd;m=mm;y=yy; ,在一个成员函数内部(函数体内),不需要显示指明访问的数据是哪个对象的,虽然一个类类型的所有对象都具有该类类型中定义的所有数据,但成员函数能够“知道”它在操作的数据属于激活该函数的那个对象。,在C+语言中,抽象数据类型更一般的形式为: class

4、Class_name ; 称为类类型的定义,它定义了一个新类型。Class_name是类名,也就是该类型的类型名。,结构类型中定义的数据成员并不是唯一地由结构中定义的成员函数进行操作;也可以使用结构变量.结构数据成员 的方式访问结构类型中定义的数据成员。,将struct 改为class;可以限制类型中定义的数据的访问。,class Date private: int d,m,y; public:void init_date(int,int,int); Date add_day(int n); ;,其中:public 将类类型中的成员分为两部分,第一部分为私有段,它们只能够被成员函数访问;第二部

5、分为公有段,构成该类类型的对象的访问接口。,注意:结构(struct)是一种特殊的类类型;结构缺省段约束符(private、protected和public)说明的成员是公有段成员。,一个类类型中可以有两种成员:数据和操作。在C+中称它们为数据成员和成员函数。根据它们的被访问权限,成员又可以分为私有段成员、保护段成员和公有段成员。,class 类名 private: /定义私有段成员私有段数据和函数定义;public: /定义公有段成员公有段数据和函数定义;,其中,类名是一个标识符,代表类类型的类型名;private、public称为段约束 符,其中private可以缺省(即没有被段约束符说明

6、的成员就是私有段成员);,定义公有和私有成员的顺序可以是任意的。, 以内的部分 称为类内; 以外的部分称为类外。,3.1.2 数据封装,一个类的定义实现了数据封装:类外不可见:(即封装起来的部分) 私有段数据 私有段函数原型 私有段函数和公有段函数的实现,类外可见:类向外提供部分公有段数据公有段函数原型,class Date int d,m,y;public:void init_date(int d1,int m1,int y1) Date add_day(int n) ;,void main( ) Date today,tomorrow;today. init_date(12,3,2003)

7、; tomorrow=today.add_day(1);tomorrow.d+; /error ,注意:,数据封装是一个相对的概念,只是对于类外而言,而对于类内,所有成员都是互相可见的。一个类的成员函数的实现,可以在类内完成,也可以放在类外实现,但函数本身仍然是类内的函数。,在类中定义的函数,自动默认为内联函数。 类外实现的函数,不是内联函数。内外可以在原型前加上inline,使之成为内联函数。,如:,inline void Date: init_date(int dd,int mm,int yy) d=dd;m=mm;y=yy; ,3.1.3 类的实例就是对象,一个类可以定义多个对象,每个对

8、象都包含类中定义的各个数据成员的存储空间,它们共享类中定义的成员函数。,一个类应该包括哪些数据成员,可以从两个方面考虑:所有这个类的对象都应该有什么属性;每一个具体的该类的对象应该包括哪些属性。,如对圆的考虑,所有的圆都应该有圆心和半径两个属性;每一个具体的圆应该包括自己的圆心和半径。,class Circle int x; int y; float radius;public:void set_xy_r(int a,int b,float r);void move(int newx,int newy);;,所有的圆的对象具有自己的圆心和半径,而共享所有对圆的操作。,类与对象的关系就类似于整数

9、类型 int 与整型变量的关系。类和整数类型 int代表的是一般的概念,对象和整型变量代表的是具体的实例。,类代表了一组对象的共同性;对象代表了具体的性质。,类在概念上是一种抽象机制,它抽象了一类对象的存储和操作特性。,在系统实现中,类是一 种共享机制,它提供了一类对象共享其类的操作实现。,类是一种封装机制,它将一组数据和对该组数据的操作封装在一起。,类是对象的模型,对象承袭了类中的数据和方法(操作)。只是各实例对象的数据初始化状态和各个数据成员的值不同。,3.1.4 类外访问成员的方法,类外访问成员的方法为: 对象.公有成员函数名(实参表) 对象.公有数据,或定义一个指向对象的指针来访问公有

10、段的成员。方式为: 指针-公有成员函数(实参表) 指针-公有数据,或者 (*指针).公有成员函数(实参表) (* 指针).公有段的数据,通过使用类的公有段成员来访问这个类。因此,类的公有段成员(公有段数据和公有段成员 函数的函数原型)提供了类的外部界面,而私有段成员以及所有段成员函数的实现细节(函数体部分)则由类封装起来,让类的使用者看不到。,在C+语言中,私有数据只能严格通过成员函数访问,任何类外(除了友元)对私有数据的访问都是非法的。使用私有数据这一语言特性来隐藏由类对象操纵的数据;,然后提供一些成员函数来访问这些数据,但隐藏了改变这些数据的能力和实现细节。这样,使得类对数据的描述和类提供

11、给外部世界来处理数据的界面这两件事互相独立,这就给出了面向对象的重要性。,一个类的重要性在于它对外部世界的一组对象描述了同一界面 ,至于怎样去实现这些功能,仅仅是类内部关心的事。各个对象通过该界面完成各项功能。,3.1.5 类类型符合抽象原则,抽象是指对于一个系统的简化的描述。在面向对象的程序设计语言中,使用数据封装机制实现信息隐蔽。数据封装将一个数据和与这个数据有关的操作集合封装在一起,形成一个能动的实体,称为对象。,用户不必知道对象行为的实现细节,只需根据对象提供的外部接口访问对象。,类是C+的关键概念,是一种用户定义的类型;类是数据隐藏和封装的单位,它将细节封装起来,只允许通过公有段的数

12、据和函数被访问,从而支持了数据抽象的机制。,3.1.6 C+的类,C+语言的类共有三种方式:class类、struct类和union类。 1 class类class类是C+语言中最典型的抽象数据类型。,1) class类的一般形式,class类名 private:私有段数据及函数;public:公有段数据及函数; ;,2) 无名类:,没有类名的类称为无名类。class global; 无名类只能定义一个对象。,3)空类:class empty ; 空类没有任何成员,包括数据和函数。空类可以定义多个对象,各个对象具有不同的地址。,2 类与结构,在C+中,结构是另外一种形式的类。C+中的结构也可以

13、包括数据和成员函数。C+ +的结构和类的差别在于缺省时,类的成员是私有的,而结构的成员是公有的。,除此以外, 类与结构有完全相同的功能。所以结构又称为其全部成员都是公有成员的类。,struct 类包括的数据成员和成员函数都是公有的。如果要在结构类中定义私有数据,需要显式地给出关键字 private。,一般情况下,C+程序员都用类来定义对象的形式,而用C的方式使用结构。,3 类与联合,联合是将所有元素都存储在同一位置上的结构。在C+中,联合也是一种类。联合的所有成员只能为公有成员。关键字 private不能用于联合(protected也不能用)。,注意:虽然 C+ 赋予联合更大的能力及灵活性,并

14、不意味必须以这种方式来使用它们。如果仅需 C 式的联合,最好以 C 的方式使用它。,3.2 构造函数和析构函数,一个类中的数据成员是不能直接初始化的。class X int num=0; /错误 ;,class Date int d,m,y;public:void init_date(int,int,int); ;,使用像init_date()这样的成员函数初始化类的对象(的数据成员)是不好的,也容易出错。,因为不是所有的对象都需要初始化;程序员也可能忘记去调用该函数(没有进行初始化)或调用它多次(初始化多次)。,使用构造函数完成初始化任务。 构造函数是类的一个特殊成员函数,没有返回类型,可以

15、有参数,函数名和类名一样。,当创建类的一个新对象时,自动调用构造函数,完成初始化工作,需要注意构造函数是否有参数,以及参数的个数、类型。,构造函数的作用为: 1分配一个对象的数据成员的存储空间, 该功能由系统自动完成 。 2执行构造函数(体),一般是初始化一个对象的数据成员。,构造函数的函数体完成初始化某个对象(新对象)的数据成员的任务,若希望该类所有对象的初始值相同,构造函数可以不使用参数;,若希望该类所有新定义的对象的初始值不相同,就需要通过使用带参数的构造函数。,构造函数初始化数据成员: 1)赋值语句的方式; 2)表达式表的方式。 对于特殊的数据成员的初始化,只能采取表达式表的方式。,c

16、lass Circle int x; int y;float radius;public:Circle( )x=0; y=0;void set_xy(int a,int b); ;,Circle c1,c2; 该类的所有对象的圆心都初始化为原点。,class Circle int x; int y;float radius;public:Circle(int intx,int inty)x=intx; y=inty; ;,构造函数使用赋值语句的方式初始化数据成员。,该类的对象的圆心可以初始化为不同的位置。 例如: Circle c1(1,2),c2(3,4);,上例的构造函数也可以使用表达式表

17、的方式初始化数据成员Circle(int intx,int inty):x(intx),y(inty) ,创建对象时,需要自动调用构造函数,如果构造函数有参数,那么,创建对象时必须给出对应的构造函数的实参。有两种方式:,1)仅仅只有一个参数: 类名 对象名 = 参数; 2) 有多个参数: 类名 对象名(参数表);,class Date int d, m, y; public:Date(int dd,int mm,int yy) d=dd;m=mm;y=yy; ;,则可以定义对象并初始化。 Date today(1,7,2002); Date startday(1,1,2001); Date m

18、y_birthday; /错误 Date release1_0(10); /错误,2 重载构造函数,一个类可以提供多个构造函数,它们的参数表必须互不相同,可以提供不同的初始化的要求。,例:,class Date int d, m, y;public:Date(int ,int,int );Date(int ,int );Date(int); Date( );Date( const char * );,Date day1(12,3,2003);Date day2(12,3);Date today(12);Date july4(“12 Mar 2003”);Date guy(“12 Mar”);D

19、ate now;,3 具有缺省参数的构造函数,构造函数可以有缺省的参数。 注意:如果一个成员函数具有缺省参数, 在类外实现该成员函数时,不能再说明缺省值。,class Date int d, m, y;public:Date(int dd=0,int mm=0,int yy=0);,Date:Date(int dd,int mm,int yy),在使用具有缺省参数的构造函数时,要谨防二义性。例如: class X public: X( ); X(int i=0); ;,void main( ) X one(10); /正确。 X two; 存在二义性,是调用X : X( ) 还是调用X : X

20、(int=0),4 缺省的构造函数,用户定义的类类型中,可以没有构造函数,系统会自动给该类类型生成一个没有参数的构造函数,不作任何的初始化工作。当建立一个对象时,自动调用这个缺省的构造函数。,但是,一个类类型如果有const成员或引用成员,就不能使用缺省的构造函数。必须使用用户定义的构造函数进行初始化;而且只能使用表达式表的方式进行初始化。,struct Xconst int a;const int /错误,struct Xconst int a;const int /正确,struct Xconst int a;const int ,5 析构函数,与构造函数对应的是析构函数。C+ 通过析构函

21、数来处理对象的善后工作。 析构函数没有返回类型,没有参数,函数名是类名前加“”。,析构函数的作用为: (1)执行析构函数(一般没有具体的工作); (2)释放对象的存储空间。(该功能由系统自动完成。),可以使用完全限定名方式显式地调用析构函数;若没有显式调用,则在一个对象的作用域结束时,系统自动调用析构函数。 objX.X:X( );,系统自动调用构造函数和自动调用析构函数的顺序是相反的。 用户定义的类类型中,可以没有析构函数,系统会自动给该类类型生成一个析构函数。,6 对象的创建和释放,可以创建不同形式的各类对象: 1)命名的自动对象:每次进入该对象的作用域,都需要调用构造函数;每次退出该对象

22、的作用域,都需要调用析构函数;,class Table ; void f(int a) Table aa;Table bb;if (a0) Table cc; Table dd; 若有 f(10) ;,则调用构造函数的顺序:aa,bb,cc,dd 调用析构函数的顺序:cc,dd,bb,aa,2)由对象(动态对象):使用new创建对象(实际上调用构造函数),使用delete释放对象(实际上调用析构函数);当使用delete释放对象后,该对象就不能再被使用。如果构造函数有参数,也必须给出实参。,class Table public:Table( ); Table * p=new Table();

23、/调用构造函数 delete p; /调用析构函数,3)非静态的成员对象(子对象):是指作为另一个类的数据成员的对象,子对象的创建和释放与包含它的对象的创建和释放同时进行;,4)对象数组:数组元素创建和释放时,对象数组元素(数组元素也是对象)也被创建和释放; 允许构造函数带缺省参数常用来把对象数组进行初始化。,5)局部的静态对象:当第一次进入它的作用域时,调用构造函数;当整个程序结束时,调用析构函数;,6)全局对象、命名空间内的对象和全局的静态对象:在程序运行时调用构造函数创建它们;当整个程序结束时,调用析构函数释放它们;,注意:,使用系统函数exit终止一个程序的运行时,也调用析构函数释放全

24、局对象和静态对象,为防止程序无限的递归调用,在析构函数中不使用函数exit,必要时可以使用函数abort。,7)表达式的局部对象:进入表达式时创建该对象,离开表达式时释放该对象; 8)内存对象:指定内存位置的对象,由分配和定位函数的参数指定内存位置。,3.2.2 拷贝构造函数 构造函数的参数可以是任何类型参数,甚至可以将自己类对象的引用作为参数,称它为拷贝构造函数。,拷贝构造函数有两个含义:首先,它是一个构造函数,当创建一个新对象时,系统自动调用它;其次,它将一个已经定义过的对象(参数代表的对象)的数据成员逐一对应地拷贝给新对象。,如果一个类没有定义拷贝构造函数,C+可以为该类产生一个缺省的拷

25、贝构造函数。,拷贝构造函数的作用,创建一个新对象,并将一个已存在的对象拷贝到这个新对象 对象本身做参数(将实参对象拷贝给形参对象) 函数返回一个对象(拷贝返回的对象给一个临时对象),class A int x;int y; public: A(int,int); A(const A ,A a(10,20); /调用A(int,int) A b(a); /调用A(const A ,这是拷贝构造函数的典型使用,它表明当我们创建一个新对象,并希望将一个已存在的对象拷贝到这个新对象时,系统自动调用拷贝构造函数。,类对象的拷贝还发生在对象本身作参数函数和函数返回对象的情形。,class string i

26、nt length; char * contents; int who; public: string(int id) length=0;contents=NULL; who=id; ;,string g(string arg) return (arg); void main( ) string s = 1;string t=g(s); ,在 main( )函数中,函数调用 g(s)发生后,拷贝构造函数将参数s(是string的对象,其值为0,NULL,1)拷贝到栈上,即在栈上创建一个临时对象arg。,当从函数g( )返回时,要从栈上将arg 对象传送出来,也常要创建一个临时对象,这时又调用一

27、次拷贝构造函数。这个临时对象紧接着赋值给string对象t。,类是一种用户定义的类型,可能简单,也可能复杂,系统难以把握。当类的对象本身作为函数参数、函数的返回值或者其他需要拷贝类对象的情况下,系统很难提供一个统一的拷贝函数以适应各类对象的拷贝。,因此,C设置拷贝构造函数,不管拷贝构造函数是缺省的,还是由用户提供,它都属于一个具体的类。这样,当需要拷贝类对象时,调用这个类的拷贝构造函数。,3.2.3 类的对象的初始化,初始化有许多表示法,C+语言允许下述三种表示方法。 (1)初始值表的方法: 这种方法对结构和数组的初始化很适合。,(2)赋值表达式的方法int num=1;char * p =

28、“No.4.op.29”; 适于简单变量或指针类型的初始化。,(3)表达式表的方法int num(1);char * p ( “No.4.op.29”);,在C+中,类的对象的数据成员的初始化一般通过构造函数进行。若构造函数有参数,则在创建对象时,必须给出实参(既对象的初始值),,方法为: 表达式表的方法:Class_Name Object(); 赋值表达式的方法: Class_Name Object=;,当初始化时,构造函数又可以通过两种方式将初始值赋给对象的数据成员。 (a)接受该值作为参量,并在构造函数体里使用赋值语句对数据成员进行赋值。,class X int a,b;public:(

29、int i,int j) a=i; b=j; ;,(2)使用函数体前的初始值表, class X int a,b;public:X(int i, int j) : a(i),b(j) ;,这种初始化方式用于类中的常量成员和引用成员的初始化;派生类初始化基类对象和子对象的初始化。,3.3 对 象 数 组,可以创建一个类的对象数组。创建一个对象数组,每个数组元素都是一个对象,所以需要多次调用构造函数;释放对象数组,也需要多次调用析构函数。,ClassName obj_arr10; 它创建了类ClassName的一个对象数组obj_arr;有10个数组元素,每个数组元素obj_arrnum都是一个对

30、象,所以,需要10次调用构造函数。,C+语言不允许初始化对象数组(实际上的意思为: 和( )不能一起使用),所以,要创建一个类的对象数组,就对该类的构造函数有要求:,(1)没有构造函数;或 (2)有构造函数,但要有一个构造函数不带参数;或 (3)有构造函数,但要有一个构造函数具有的参数全是缺省参数。,3.4 指向对象的指针变量,在C语言中,结构分量可以通过结构变量直接存取或通过指向结构的指针来存取。类似地,在C+中,可以直接使用对象,也可通过指向对象的指针变量来使用对象。,说明指向对象的指针变量的语法与说明指向其他任何数据类型的指针变量的语法相同。,ClassName * objPointer

31、; 说明objPointer是一个指向ClassName 类的对象的指针变量,因为没有创建对象,不需要调用构造函数。,ClassName * objPointer;ClassName ClassObj;objPointer=,可以通过下面方式在类外访问一个类的成员: 指向对象指针变量-类公有成员,注意:对象的地址是用地址操作符获得的,这与获得任何其他类型变量地址的方法是相同的。,#include iostream.hclass p_example int num;public:void set_num(int val) num=val;void show_num( ) coutnumendl;

32、 ;,void main( ) p_example ob3, *p;ob0.set_num(10);ob1.set_num(20);p=&ob0; p-show_num( );p+;p-show_num( ); p-;p-show_num( );,3.5 类类型做参数类型,由于类是一个数据类型,也可以将对象作为参数传递给函数,参数传递遵循传值(或传地址)的方式,这 同所有其他的数据类型是相同的。,类类型做形参类型,3种方式: 对象本身做参数(传值) 对象引用做参数(传地址) 对象指针做参数(传值),对象本身做参数,class OBJ int num;public: void set_num(i

33、nt x) num=x;void out_num( ) coutnum ; ;,void fun(OBJ objx) objx.out_num( );objx.set_num(100);objx.out_num( ); 通过拷贝构造函数将实参对象拷贝到形参对象,void main( ) OBJ obj;obj.set_num(10);fun(obj);obj.out_num( ); 结果为 10 100 10,对象本身作形参,通过拷贝构造函数将实参对象拷贝到形参对象,实参对象和形参对象是两个不同的对象,对形参对象的修改,不会影响到实参对象。,对象引用做参数,void fun(OBJ ,void

34、 main( ) OBJ obj;obj.set_num(10);fun(obj);obj.out_num( ); /10 100 100,对象引用作形参,形参就是实参,实参对象和形参对象是同一个对象,对形参对象的修改,就是对实参对象的修改。,对象指针做参数,void fun(OBJ * objp) objp-out_num( );objp-set_num(100);objp-out_num( );,void main( ) OBJ obj;obj.set_num(10);fun(/10 100 100,对象指针作形参,它指向实参对象,通过间接的方式访问和修改它指向对象,实际上就是访问和修改实

35、参对象。,总之:,对象本身做参数,对形参的修改都不影响实参对象; 对象引用做参数,对形参的修改就是对实参对象的修改; 对象指针做参数,对指向的对象的修改就是修改实参对象。,3.6 关键字this,C+为成员函数提供了一个称为this的指针,因此,常常称成员函数拥有this指针。,this是一个隐含的指针,不能被显式声明,它只是一个形参,是一个局部变量,它在任何一个非静态成员函数里都存在,它局部于某一对象。,this指针是一个常指针,可以表示为(但不能显式声明):X * const this /X是类名 因此,this指针不能被修改和赋值。,某个对象obj调用某个成员函数fun,则fun函数的t

36、his指针就指向对象obj,而且在该成员函数fun中,this指针始终指向对象obj。,不管是在类外访问类的公有成员,还是在类内访问类的成员(公有或私有成员),都需要使用对象.成员 或指向对象的指针-成员 的方式 。,只不过在类内,若是直接访问成员(即没有指明是哪个对象或者哪个指向对象的指针访问成员)的方式,实际就是this-成员的方式。,访问成员函数的形式为:对象.成员函数(参数表); 或指针-成员函数(参数表);,实际上,还需要另一个参数,作为this的实参,格式为: 对象.成员函数(参数表,成员函数通过this指针,“知道”访问的数据是哪个对象的。,class INT int a; pu

37、blic:void set(int n) a=n;int get ( ) return a; ;,void main( ) INT A,*P;P= ,系统将上述程序改造为:,class INT int a; public:void set(int n,INT * const this) this-a=n;int get(INT * const this ) return this-a; ;,void main( ) INT A,* P;Pint=,class INT int num;public:void set(int x) num=x;void out() coutnum ;,void f

38、un( INT obj) INT funObj;num=10;obj.num=20;funObj.num=30;out( );obj.out( ); funObj.out( ); set(40); obj.set(50); funObj.set(60); out( );obj.out( );funObj.out( );,void main( ) INT mainObj;mainObj.set(1);mainObj.out( );mainObj.fun(mainObj);mainObj.out( ); ,则程序输出:1 10 20 30 40 50 60 40,this指针是一个常指针,还可以使

39、用const说明符将this声明为指向常量的常指针。,在类中,一个成员函数的原型后跟一个const,该函数称为const成员函数;它说明此时this的类型是:const X * const this,const成员函数的特点是它不能修改this所指的对象的成员。,class INTEGER int a; public:int crease( ) return +a; int decrease( ) const return -a; / 错误;,3.7 静 态 成 员,关键字static(表示静态的)可以用于说明一个类的成员(包括数据成员和成员函数),称它们为static成员。,一 静态数据成员

40、,在一个类中,若将一个数据说明前加上static,则该数据称为静态数据,static数据成员被该类的所有对象共享。无论建立多少个该类的对象,都只有一个静态数据的存储空间。,static数据成员的存储空间不由构造函数分配;而每个对象都具有非static的数据成员各自的存储空间(由构造函数分配)。,构造函数的作用为: 1)分配对象包含的非静态数据成员的存储空间; 2)初始化对象包含的非静态数据成员。,static数据成员属于类,而不属于对象;static数据成员也分为公有和私有的;在类外只能 访问公有的static数据成员,且访问方式为:类名:static公有数据成员,在类内可以访问所有的stat

41、ic数据成员,采用直接访问方式。,注意:一个类的static数据成员不做自动初始化(而一个函数内的static数据若没有显示初 始化,则自动初始化为0)。,类的static数据成员必须在类外进行定义,方式为: type 类名:static成员;,类的static数据成员若要初始化,在类外定义该static数据成员时进行。 定义且初始化的方式为:type 类名:static成员=初值;,class counter static int count;public:void set(int num) count=num; void show( ) coutcount; ;,int counter:c

42、ount=0;void main( ) counter a,b;a.show( ); b.show( );a.set(10); a.show( );b.show( ); / 001010,例子:,考虑书店对书籍的管理。每本书都有自己的书名、价格等属性;在考虑所有书的总价格时,可以将总价格定义为全局的变量,,class bookschar * name;float price; ;float all_pri; /全局变量,但总价格是与书有关的属性,只是不属于每本书而已,可以将总价格定义为static成员。,class books char * name;float price;static fl

43、oat all_pri; ; float books:all_pri=0;,一个类对象做自己类的成员,一个类可以使用自己类的static对象做成员; 但不能使用自己类的非static对象做成员。,class Date int d, m, y; static Date defdate; Date date; /错误 public: Date(int dd=0,int mm=0,int yy=0); ;,Date Date:defdate(1,1,1); /初始化,思考:,对于static数据成员,拷贝构造函数还需要特殊考虑static数据成员的复制。,仓库管理中,假定现在只关心货物的重量,可以使

44、用static数据表示总重量。,class Goods float each_weight; static float all_weight;public: Goods(float weight)each_weight=weight; Goods( )all_weight-=each_weight;,Goods(const Goods ,如果一个成员函数访问的只是static数据,它的this指针是没有用处的。为了解决这个问题,允许定义static成员函数。,二 静态成员函数,成员函数也能被说明为静态的。static成员函数没有this指针。static成员函数只属于一个类。 因此,在类外调用

45、一个公有static成员函数,不需要指明对象或指向对象的指针。,具体方式为:类名:static公有函数()对象.static公有函数(),而在类内,采用直接调用static成员函数(包括公有的和私有的)的方式。,static成员函数没有this指针,因此,一般使用static成员函数来访问static数据成员;,若在static成员函数中要访问非static成员时, 必须明确指出该static成员函数在哪个对象上操作,必须要有限定词(即需要通过对象或指向对象的指针进行),,一般需要类类型作静态成员函数的参数类型(除非是使用全局对象)。,class INTEGER int member_int;

46、static int static_int;public:static void func(int numb1,int numb2, INTEGER * ptr); ;,int INTEGER: static_int=0; void INTEGER :func(int numb1,int numb2, INTEGER * ptr) /类外实现时,不加static member_int=numb1; /错误, ptr- member_int=numb1; /正确 static_int=numb2; /正确,void main( ) X obj;X:func(1,2, / 正确,3.8 友 元 关

47、 系,一个对象的私有数据,只能通过成员函数进行访问,这是一堵不透明的墙。这种限制性的用法给两个类必须共享同一函数的情形带来了较大的开销。,出于效率(而非技术上必须)考虑,C+ 提供了一种辅助手段,允许外面的类或函数去访问一个类的私有数据。 友元关系有3种 。,3.8.1 友元函数,类X的友元 F 可以是一个函数,它虽然不是X的成员函数,但能访问X的私有成员和保护段的成员,除了具有这一访问权限外,F在作用域、声明和定义等方面都是一普通的函数。,class INT int pri;public: int pub; void set(int n1,int n2) pri=n1; pub=n2; ;,void out(INT numobj) coutnumobj.pri“ ”; /错误 类外访问私有成员coutnumobj.pub; ,void main( ) INT obj;obj.set(12,24);out(obj); ,为了使类外的函数能够访问一个类的私有数据,可以将该函数在类中声明为类的友元函数。,将上例修改为,class INT int pri;public: int pub; friend void out(INT numobj); /*将类外函数out( )声明为类INT的友元函数*/ void set() ;,

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

当前位置:首页 > 企业管理 > 管理学资料

本站链接:文库   一言   我酷   合作


客服QQ:2549714901微博号:道客多多官方知乎号:道客多多

经营许可证编号: 粤ICP备2021046453号世界地图

道客多多©版权所有2020-2025营业执照举报