chap6_类与对象3.ppt_第1页
chap6_类与对象3.ppt_第2页
chap6_类与对象3.ppt_第3页
chap6_类与对象3.ppt_第4页
chap6_类与对象3.ppt_第5页
已阅读5页,还剩89页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

1、第6讲 类与对象的更多内容,对象数组* 对象指针变量* this指针 对象与函数 变量作用域 类对象作为成员 静态成员 友元 类模板,1 对象数组,对象数组 一个数组中的每个数组元素都为同一类的对象。 对象数组的创建 数组长度必须为常量;若在创建数组的同时为每个数组元素进行初始化,则可以省略数组长度。 系统会创建数组中的每个对象元素,并调用相应的构造函数去初始化每个数组元素。 由于创建对象数组即创建多个对象,也要调用构造函数,因此对象数组的声明形式与构造函数有关。 数组的生命期结束时,会为每一个数组元素调用析构函数。,创建对象数组,创建对象数组的形式1 类名 数组名常量表达式; 此时该类中:

2、没有自定义构造函数,或 自定义了无参构造函数,或 自定义了有参构造函数,但为每个参数提供了默认值。 若不满足以上三个条件之一,则不能使用该形式创建对象数组。,/ circle.h class Circle private: double radius; public: Circle(); double getArea(); double getRadius(); void setRadius(double); ;,/ circle.h class Circle private: double radius; public: double getArea(); double getRadius(

3、); void setRadius(double); ;,正确,由于该类中没有自定义构造函数,因此将分别调用3次系统提供的默认构造函数。,正确,由于该类中提供了自定义的无参构造函数,此时将分别调用3次该无参构造函数。,Circle c3;,Circle c3;,举例说明创建对象数组:Circle类,/ circle.h class Circle private: double radius; public: Circle(double=1); double getArea(); double getRadius(); void setRadius(double); ;,正确,由于该类中提供了自

4、定义的有参构造函数,且该构造函数带默认参数值,因此将分别调用3次该构造函数,将3个数组元素的数据成员均初始化为1。,Circle c3;,创建对象数组的形式为:,举例说明创建对象数组:Circle类,创建对象数组的形式2: 类名 数组名常量表达式=类名(参数表),类名(参数表); 此时该类中: 只有自定义的有参构造函数且没有提供默认参数值。 若类中只提供了自定义有参构造函数且没有提供默认参数值,将不能使用第一种形式创建对象数组。,创建对象数组,/ circle.h class Circle private: double radius; public: Circle(double r); do

5、uble getArea(); double getRadius(); void setRadius(double); ;,正确,由于该类中提供了自定义的有参构造函数,且该构造函数无默认参数值,因此将分别调用3次该构造函数。,Circle c3=Circle(1), Circle(2), Circle(3);,Circle c3;,错误,因为该类中没有提供无参构造函数。,等价于:Circle c3=1,2,3; Circle c =1,2,3;,举例说明创建对象数组:Circle类,创建对象数组的形式为:,若希望在程序中使用多种形式创建对象数组,则应该在类中提供多种形式的构造函数。 重载构造函

6、数 同时提供无参构造函数和有参构造函数 提供带默认参数值的构造函数 若类中既提供了无参构造函数也提供了有参构造函数(即重载)或提供了带默认参数值的构造函数,则可以使用多种形式创建对象数组,此时可只给部分数组元素初始化,未初始化的数组元素将自动调用无参构造函数进行初始化。,创建对象数组,/ circle.h class Circle private: double radius; public: Circle(); Circle(double); double getArea(); double getRadius(); void setRadius(double); ;,/ circle.h

7、class Circle private: double radius; public: Circle(double=1); double getArea(); double getRadius(); void setRadius(double); ;,创建对象数组的形式为:,Circle a3; Circle b3=Circle(1); Circle c3=Circle(1), Circle(2); Circle d3=Circle(1), Circle(2), Circle(3); Circle e3=Circle(),Circle(2),Circle(3); Circle f3=1,2,

8、3; Circle g3=2;,/ rectangle.h class Rectangle private: double width,height; public: Rectangle(); double getArea(); double getPerimeter(); void getWH(double,举例说明创建对象数组:Rectangle类,此时创建对象数组的形式唯一,即: Rectangle a3;,/ rectangle.h class Rectangle private: double width,height; public: Rectangle(double, doubl

9、e ); double getArea(); double getPerimeter(); void getWH(double,举例说明创建对象数组:Rectangle类,此时创建对象数组的形式唯一,必须为每个数组元素初始化。 Rectangle b3=Rectangle(10,1), Rectangle(15,2), Rectangle(20,3);,/ rectangle.h class Rectangle private: double width,height; public: Rectangle(double, double =0); double getArea(); double

10、 getPerimeter(); void getWH(double,举例说明创建对象数组:Rectangle类,此时创建对象数组时必须为第一个数据成员提供参数,不能只给部分数组元素初始化。 Rectangle b3=Rectangle(10,1), Rectangle(15,2), Rectangle(20,3); Rectangle c3=Rectangle(10), Rectangle(15), Rectangle(20,3); Rectangle d3=10, 15,25;,Error: Rectangle a3; Rectangle e3=10, 15;,/ rectangle.h

11、class Rectangle private: double width,height; public: Rectangle(double=0, double =0); double getArea(); double getPerimeter(); void getWH(double,举例说明创建对象数组:Rectangle类,此时创建对象数组的形式多样,可只给部分初始化。 Rectangle a3; Rectangle b3=Rectangle(10,1), Rectangle(15,2), Rectangle(20,3); Rectangle c3=Rectangle(), Recta

12、ngle(15), Rectangle(20,3); Rectangle d3=10, 15; ,/ rectangle.h class Rectangle private: double width,height; public: Rectangle( ); Rectangle(double); Rectangle(double, double ); double getArea(); double getPerimeter(); void getWH(double,举例说明创建对象数组:Rectangle类,这三个重载的构造函数等价于为两个数据成员同时提供默认参数值的构造函数。 因此也可创

13、建多种形式的对象数组。,访问数组元素对象的各公有成员: 数组元素名下标.公有成员 例: double t1=c1.getRadius();,对象数组的使用,#includecircle.h #include void main() Circle c5; double sum=0; for(int i=0;i5;i+) ci.setRadius(i+1); sum+=ci.getArea(); coutsumendl; ,2 对象指针变量,创建对象时,系统会为该对象分配相应的存储空间存放其数据成员,其起始地址就是对象的地址即指针。 对象指针:指向对象的指针。 对象指针变量定义形式: 类名 *对象

14、指针变量名; Circle c, *p= (小括号不能省略),在堆中创建动态对象,在堆中动态申请、释放对象内存空间时,要使用对象指针变量、new和 delete运算符。 用new为对象申请空间时需调用构造函数,此时创建了一个对象。如: Circle *p1= new Circle; /调用无参构造函数 或:Circle *p1= new Circle(); Circle *p2=new Circle(2.5); /调用有参的构造函数 Circle *p3= new Circle 3; 此时必须调用无参构造函数,否则不能动态创建!调用3次 用delete命令为对象删除动态空间时,将调用析构函数。

15、 delete p1; /调用析构函数 delete p3; /不可省略,否则出现运行错误 /调用3次析构函数,3 this指针,类成员的存储(创建对象时存储空间的分配) 只为对象的数据成员分配相应的存储空间,成员函数存储在于代码区。创建n个对象,每个对象都有各自的数据成员存储空间,而n个对象都调用相同的函数代码段。 成员函数如何区分是哪个对象在对其进行调用呢?,#include #include Circle.h void main() Circle c1,c2; coutc1.getArea(); cout c2. getArea(); c1.setRadius(3); c2. setRa

16、dius(2.5); cout c1.getArea(); cout c2. getArea(); ,代码区,栈,getArea,setRadius,radius,radius,getRadius,c1,c2,this指针,this是一个指向调用该函数的对象的常量指针。 隐含在类的成员函数中的一个对象指针,每当成员函数被调用时,this指针自动指向调用该成员函数的对象(即this指针为当前对象的地址)。 this指针的系统定义格式为: 类名 *const this; 该指针是系统自动产生的,不需要人为定义;并且它是常量指针,不能被赋值,只能使用它。 利用this指针能保证对象的每一个成员函数能

17、够访问其对应的数据成员,从而使C+中的各个对象既具有自己的数据成员空间,同时又可共用同一个成员函数代码。 成员函数可通过this指针直接使用同类的其它成员。,this 指针是隐式使用的,作为参数被传递给成员函数。,double Circle:getArea() return radius* radius *3.14159; ,double Circle:getArea( Circle *this) /即在形参表中增加一个this指针 return this-radius * this-radius *3.14159; ,在调用成员函数时,实际上是以以下方式调用: cout circle1.ge

18、tArea( ,这些都是编译系统自动实现的,不必人为地在形参中增加this指针,在需要时也可以显式地使用this指针。 由于当成员函数的形参/局部变量与类中数据成员同名时,数据成员被屏蔽,因此若需要在成员函数中访问被屏蔽的数据成员,可使用this指针进行访问,形式为: this-数据成员 (*this).数据成员 注意不能写成: *this.数据成员 因为成员运算符. 的优先级别高于指针运算法*。 “调用对象a的成员函数f”的含义: 在调用成员函数f时使this指针指向对象a,对f函数而言a为当前对象,从而在f函数中访问对象a的数据成员。 利用this指针,可使形参名与数据成员相同。,this

19、指针,例:Circle类定义(使用this),/* class declaration,circle.h */ class Circle private: double radius; public: double getArea(); double getRadius(); void setRadius(double); ;,/* circle.cpp, class definition */ double Circle:getArea() return radius* radius *3.14159; double Circle:getRadius() return radius; voi

20、d Circle:setRadius(double radius) this-radius=radius=0? radius:0; ,理解this的含义,#include /类的声明clock.h class Clock public: Clock(int h,int m,int s); /构造函数 Clock() /析构函数 coutthis=thisendl; void setTime(int h,int m,int s); void showTime(); private: int hour,minute,second; /数据成员 ; Clock:Clock(int h,int m,i

21、nt s) /类的实现clock.cpp coutthis of construction= thisendl; hour=h; minute=m; second=s; void Clock: setTime(int h,int m,int s) coutthis of Settime = thisendl; hour=h; minute=m; second=s; void Clock:showTime() coutthis of Showtime = thisendl; coutIts hour:minute: second now.endl; ,/testClock.cpp #includ

22、e #include Clock.h void main() Clock Clk1(1,2,3),Clk2(4,5,6); cout ,4 对象与函数,在函数调用时,对象名可作为实参传递给函数 传值方式 传对象值:要调用复制构造函数 传对象地址值:不调用复制构造函数 引用方式 不调用复制构造函数 通常采用引用方式,因为: 按值方式需要额外的时间和内存空间; 使用对象引用参数比使用指针参数更为简单。 函数调用结束后,对象作为返回值。 若对象名作为函数的返回值,则将调用复制构造函数。,对象与函数使用举例:Complex类,/complex.h, Complex类的声明 class Complex

23、public: Complex(double r=0,double i=0); void setRI(double r ,double i); void getRI(double,在Complex类中增加成员函数addition,实现当前对象与给定对象之间的加法运算,返回两者之和(采用对象值传递)。,Complex类的使用,#includecomplex.h void main() Complex c1(1,1),c2(2,3); Complex c=c1; c=c1.addition (c2); c.print(); ,运行结果: copy constructor is called cop

24、y constructor is called copy constructor is called 3+4i,c=c1.addition (c2); 对addition函数而言,c1为当前对象,c2为实参,调用addition函数后,函数返回值赋予c对象。,Complex类的实现 part1,#include complex.h /complex.cpp #include Complex Complex:addition( Complex c ) Complex t; t.real =real+c.real; t.imag =imag+c.imag ; return t; /复制构造函数定义

25、 Complex:Complex(Complex cout copy constructor is called; /其他成员函数的定义见下页,/test.cpp #includecomplex.h void main() Complex c1(1,1),c2(2,3); Complex c=c1; c=c1.addition (c2); c.print(); ,Complex类的使用,运行结果: copy constructor is called copy constructor is called copy constructor is called 3+4i,/complex.cpp

26、Complex:Complex(double r,double i) real=r, imag=i; void Complex:setRI(double r,double i) real=r,imag=i; void Complex:getRI(double ,Complex类的实现part2,分析:,c=c1.addition (c2); 对addition函数而言,c1为当前对象,c2为实参,由于是对象值传递,因此在函数调用时,为形参对象c分配完内存后调用复制构造函数将c2成员的值赋予c的各成员;addition函数调用结束后,函数要返回对象t,此时将生成匿名对象,调用复制构造函数将t的值

27、赋予该匿名对象,而后将匿名对象的值赋予对象c。,Complex Complex:addition( Complex c ) Complex t; t.real =real+c.real; t.imag =imag+c.imag ; return t; ,改进:,/complex.h, Complex类的声明 class Complex public: Complex(double r=0,double i=0); void setRI(double r ,double i); void getRI(double,Complex类中成员函数addition, 采用引用传递,形参为引用类型,实参为

28、对象名。当调用该函数时,将不再调用复制构造函数,效率高。,Complex Complex:addition( Complex ,例:对象作为参数,/* class declaration, circle.h */ class Circle private: double radius; public: Circle(); Circle(double); double getArea(); double getRadius(); void setRadius(double); ;,/circle.cpp, class definition #include circle.h Circle:Cir

29、cle() radius=1; Circle:Circle(double newRadius) radius=newRadius; double Circle:getArea() return radius* radius *3.14159; double Circle:getRadius() return radius; void Circle:setRadius(double r) radius=r; ,#include circle.h #include void printCircle(Circle c) / (Circle 传址 ,5 变量作用域,变量的作用域 是指程序中变量有效的区

30、域。 变量的作用域分为:全局域、局部域和类作用域。 局部变量:在函数内声明,只能在函数内部使用。 全局变量:在函数体外声明 类作用域 即类声明和类的实现范围。类的所有成员都在类的作用域中,且具有无限制的访问权,类的所有成员都可以访问该类的所有数据成员和成员函数。而类内成员对类作用域以外的数据或函数进行的访问是受限制的;同样,类作用域以外的数据或函数对类内成员的访问也是受限制的。 数据成员可被类中所有成员函数访问。类似于全局变量,但是数据成员和成员函数在类中的声明顺序可以是任意的(不影响作用域)。 如果成员函数内一个局部变量与一个数据成员同名,则数据成员将被屏蔽,因为局部变量的优先级更高。,理解

31、:全局变量与数据成员,#include int t=0; /全局变量 class Ctest public: int t; void f(); private: int number; float socre; ; void Ctest:f()/f()函数为test类的成员函数 :t=11;/该变量为全局变量t t=100;/该变量为test类的数据成员 void main() Ctest a; a.f(); couttendl; /该变量为全局变量t couta.tendl; ,数据成员屏蔽全局变量,可利用作用域操作符:区分全局变量和类的数据成员,理解:局部变量与数据成员,#include

32、class CTest public: void f1(); void f2(); void show() coutm = mendl; private: int m; ; void CTest:f1() m = 5; void CTest:f2() int m;/m为函数f2的局部变量, m = 10;/为局部变量m赋值 ,void main() CTest a; a.f1();/访问类的公有成员 a.show(); a.f2(); a.show(); ,类成员函数的局部变量隐藏了类的同名数据成员,利用this指针可访问数据成员。,this-m=10; /为数据成员m赋值,6 对象作类的数据

33、成员,C+中,类的数据成员可以是对象。 为具有对象成员的类创建对象时,各个对象成员也将被自动创建。因此在创建包含对象成员的类的对象时,系统首先为对象成员初始化,而后再为本类的基本类型成员初始化。即先要调用对象成员的构造函数,然后再执行本类的构造函数函数体为基本数据成员初始化。 若有多个对象成员,按照对象成员声明的顺序依次调用相应的构造函数。 当对象的作用域结束时,先调用本类的析构函数,再调用对象成员的析构函数。 具有对象成员的类的构造函数的定义要使用构造函数的初始化列表形式。,构造函数初始化列表,构造函数初始化列表一般形式为:,类名:类名(形参表):对象成员1(实参表), 对象成员2(实参表)

34、, 类的基本数据类型成员的初始化 ,例:Circle类中包含两个数据成员: Point类对象center,表示圆心的坐标, double 型的数据成员radius,表示半径。,/point.h,Point类的声明 class Point int x,y; public: Point(int x1,int y1); void setXY(int x1=0,int y1=0 ); void getXY(int,/Circle类的声明circle.h #includepoint.h class Circle private: double radius; Point center;/ 对象成员 pu

35、blic: Circle(double,int,int); double getArea(); double getRadius(); voidsetRadius(double); Point getCenter(); void setCenter(int x, int y); void setCenter(Point,对象做类的数据成员例,#includepoint.h/ Point 类的实现 Point:Point(int x1,int y1) x=x1,y=y1; void Point: setXY(int x1,int y1 ) x=x1,y=y1; void Point: getXY

36、(int ,构造函数初始化列表,Circle类的构造函数的实现,#incudecircle.h Circle:Circle(double r, int x,int y) : center( x, y ) radius = r; ,创建Circle类的对象时,例如: Circle c(1.5, 1,1); 执行过程:首先调用Circle类的构造函数,将1.5、1、1作为实参传递给构造函数的对应形参;而后调用Point类的构造函数,此时x、y成为实参传递给Point类的构造函数,为center初始化;最后执行Circle类构造函数的函数体,为radius成员初始化。,错误写法:,/Circle类的

37、实现 #includecircle.h Circle:Circle(double r, int x,int y) radius = r; center = Point(x,y); 其他成员函数见下页,此时编译后出现语法错误: Point : no appropriate default constructor available 错误原因:因为此时要先为center成员初始化,而Circle类构造函数未使用构造函数初始化列表形式,因此此时会自动调用Point类的无参构造函数,而Point类中只定义了一个有参的构造函数,因此会出现如上错误提示。,/ 错误写法,说明,在定义包含有对象成员的类的构造

38、函数时,应使用构造函数的初始化列表方式。 若不使用初始化列表形式,那么系统一定会自动先调用对象成员的无参构造函数,而后再执行本类的构造函数函数体,因此如果对象成员所属的类定义中没有无参构造函数,则会出现编译错误。 改正办法: 使用构造函数初始化列表形式; 修改对象成员所属类的定义,提供无参构造函数。,#incudecircle.h Circle:Circle(double r, int x,int y) : center( x, y ) radius = r; double Circle:getArea() return radius* radius *3.14159; double Circ

39、le:getRadius() return radius; void Circle:setRadius(double r) radius=r; ,Circle类的成员函数的定义:circle.cpp,Point Circle: getCenter() return center; void Circle:setCenter(int x,int y) center=Point(x,y); void Circle:setCenter(Point ,测试Circle类,#includecircle.h #include void main() Circle c1( 1.5, 1, 1 ); cout

40、c1.getRadius (); c1.getCenter ().print(); coutc1.getArea()endl; c1.setRadius(3); Point p(2,4); c1.setCenter(p); coutc1.getArea()endl; ,总结 为具有对象成员的类创建对象时,由于系统一定会先为对象成员初始化,即自动先调用对象成员的无参构造函数,而后再执行本类的构造函数体,因此如果对象成员的类定义中没有无参构造函数,则会出现编译错误。为避免这类错误,除了采用初始化列表形式外,还可修改对象成员的类的定义,增加无参构造函数或带默认参数值的构造函数。,#include c

41、lass Point int x,y; public: Point(int x1=0,int y1=0) x=x1; y=y1; void print() cout(x,y)endl; void set(int x1=0,int y1=0) x=x1,y=y1; void get(int,Point类和Circle类的完整定义: Pont.h,#includepoint.h #include class Circle Point center; double r; public: Circle() /此处会调用Point类的无参构造 r=1; Circle(double r1) /此处会调用P

42、oint类的无参构造 r=r1; Circle(double r1,int x,int y ,):center(x,y) r=r1; void setR(double r1) r=r1; double getR() return r; ,Point getC() return center; void setC(int x,int y) center=Point(x,y); void setC(Point 0,circle.h,测试,#includecircle.h void main() Circle a; a.print (); Circle b(1.5); b.print (); Cir

43、cle c(1.5,2,2); c.print (); ,运行结果: (0,0) 1 (0,0) 1.5 (2,2) 1.5 Circle destructor.1.5 point destructor.(2,2) Circle destructor.1.5 point destructor.(0,0) Circle destructor.1 point destructor.(0,0),注意:,在circle.cpp文件中不能再包含 point.h 文件,即不能再使用#include point.h ,因为在circle.h 中已经包含了 point.h文件,若在circle.cpp中再次包

44、含则出现:Point:class type redefinition 的错误。 同理,在main.cpp中也只能包含circle.h 。 解决办法: 使用条件编译 在point.h中增加: #ifndef POINT_H #define POINT_H 在最后一行增加:#endif,对象做类的数据成员例2,#ifndef DATE_H #define DATE_H class Date public: Date(int,int,int); /用指定日期创建Date对象 void setYear(int); void setMonth(int); void setDay(int); int ge

45、tYear(); int getMonth(); int getDay(); void printDate(); private: int year,month,day; ; #endif,账户类Account中有一个数据成员openAccountDate,为Date类的对象,表示账户的开户日期。已知Date类的声明部分如文件date.h所示,Account类的声明如文件account.h所示。,date.h,#ifndef ACCOUNT_H #define ACCOUNT_H #includedate.h class Account public: Account(int,double,d

46、ouble,int,int,int); void withDraw(double);/从账户中支取指定余额 void deposit(double);/向账户中存入指定余额 void setId(int);/设置用户名 void setBalance(double);/设置余额 void setAnnualInterestRate(double);/设置年利率 int getId();/返回用户名 double getBalance();/返回余额 double getAnnualInterestRate();/返回年利率 double getMonthlyInterestRate();/返回

47、月利率 Date getOpenAccountDate(); /返回开户日期 private: int id; double balance; double annualInterestRate; Date openAccountDate; ; #endif,account 类的声明部分:account.h,对象成员,account.cpp(只列出构造函数),#include account.h / 错误方法 Account:Account(int i,double in,double b,int y,int m,int d) id=i; annualInterestRate=in; bala

48、nce=b; openAccountDate = Date(y,m,d); (其他成员函数略去),此时编译后出现语法错误: Date : no appropriate default constructor available 因为此时要调用对象成员openAccountDate的无参构造函数,而Date类中只定义了一个有参的构造函数,为此必须使用构造函数初始化列表形式来实现Account类的构造函数。,修改Date类的构造函数,在Date类的声明中修改构造函数原型说明语句为: Date(int=1900,int=1,int=1); 在Date类的实现中: #include date.h Da

49、te:Date(int y, int m ,int d) year = y; month = m; day = d; (其他成员函数略去),此时,则不必再修改Account类的构造函数,当创建Account类对象时,先调用Date类的构造函数为openAccountDate 成员初始化,而后在执行Account类的构造函数体。,如果有多个对象成员,则按照类内声明的顺序依次调用它们的构造函数,析构函数的调用顺序相反。,/student.h #include”date.h” #include”mystr.h” class CStudent public: CStudent(char *,int,i

50、nt,int,int); CStudent(); private: MyStr m_Name; Date m_Birthday; int m_Computer; ;,/student.cpp #include”student.h” #include CStudent:CStudent(char *name,int y,int m,int d,int computer):m_Name(name),m_Birthday(y,m,d) coutIn CStudent Constructorn; m_Computer=computer; CStudent:CStudent() coutIn CStud

51、ent Destructorn; void main() CStudent s1(Alice,1988,10,26,85); ,In MyStr Constructor In Date Constructor In CStudent Constructor In CStudent Destructor In Date Destructor In MyStr Destructor,多个对象成员,7 静态成员,为什么需要静态成员? 如果希望在类范围内共享数据,则需要使用静态变量(static variable),也称为类变量(class variable). 静态成员static members

52、定义类时,用关键字static声明的数据成员或成员函数称为静态成员. 静态数据成员static data field(存储在静态数据区域) 类所有对象的静态数据成员都共用同一个存储空间,即静态数据成员被类的所有对象共享. 静态成员函数static function 静态成员函数是被一个类中所有对象共享的成员函数,不属于哪个特定的对象,因此,一般只用于访问静态数据成员或全局变量,只能调用类的其它静态成员函数(无this指针,因此不能默认访问本类中的非静态成员)。 实例成员(instance members,即非静态成员) 是与类的特定对象联系在一起的,对于同一个类的不同对象,实例变量是不同的,并

53、不共享。即不同的对象具有不同的实例成员。 通常,一个类的两个对象会拥有不同的内存空间来存放它们的实例数据成员,每个对象的数据成员互不干扰。,静态数据成员的初始化,在类声明中使用static关键字进行描述。 必须在类外进行初始化,不能在类定义体内初始化(类是一种描述并非具体实现),初始化时必须加类名限定,且不加static,未初始化时系统自动赋初值为0。数据类型类名:静态数据成员初值; 数据类型类名:静态数据成员;(默认为0) 无论建立多少个该类的对象,都只有一个静态数据的拷贝,即编译器只为静态数据成员分配一份内存空间,供该类的各个对象公用。 静态数据成员可以为public或者private(此

54、时必须定义静态成员函数)。,静态成员函数,当一个成员函数被说明为static时,作为静态的成员函数属于整个类,成为此类所有对象所共享的成员函数,而不属于类中的某个对象。 在类声明中将某个成员函数声明为静态后,在类实现中不能再使用static关键字,否则出现编译错误。 静态成员函数的调用形式 类名:静态函数名() /较好,提高可读性 对象名.静态函数名() 静态成员函数没有this指针,因此它不能像一般的成员函数那样随意地访问对象中的非静态的数据成员,一般只用于访问静态数据成员或全局变量,只能调用类的其它静态成员函数。 如果静态成员函数要对对象的非静态数据成员进行操作,则对象必须以参数的形式传递

55、给静态成员函数(指出它作用在哪个对象上)。,静态与非静态成员之间的访问,静态成员函数 可直接访问静态成员(数据或函数),可直接使用其变量名来访问; 不能直接访问非静态成员 此时需要使用“对象名.成员名”(因为静态成员函数无this指针定义,不能隐含指定数据成员所属的对象)。 非静态成员函数 可以直接访问类中的静态成员数据和非静态成员数据。,静态成员的应用1:Circle类,class Circle private: double radius; static int numOfObjects; /表示已创建圆类对象的个数 public: Circle(); Circle(double); Ci

56、rcle(); double getArea(); double getRadius(); void setRadius(double); /return the number of circle objects static int getNumberOfObjects(); /返回已创建对象个数 ;,circle.h,#include circle.h int Circle:numberOfObjects=0; Circle:Circle() radius=1; numberOfObjects+; Circle:Circle(double newRadius) radius=newRadi

57、us; numberOfObjects+; double Circle:getArea() return radius* radius *3.14159; double Circle:getRadius() return radius; void Circle:setRadius(double r) radius=r; int Circle:getNumberOfObjects() return numberOfObjects; Circle:Circle() numberOfObjects-; ,Circle类的实现circle.cpp,静态数据成员的初始化,静态成员函数,静态数据成员,注意

58、:静态数据成员的初始化要放在类声明外面,此时不能再使用static关键字。,#include circle.h #include void main() Circle cir1; coutCircle:getNumberOfObjects()endl; Circle cir2(2); coutCircle:getNumberOfObjects()endl; coutcir1.getRadius ()endl; coutcir1.getArea()endl; coutcir1.getNumberOfObjects()endl; coutcir2.getRadius ()endl; coutcir2.getArea()endl; coutcir2.getNumberOfObjects()endl; ,testCircle.cpp,静态成员函数的访问形式: 类名:静态成员函数 对象名:静态成员函数,静态成员的应用,在定义类时如何确定一个变量或函数应该是实例的还是静态的? 如果变量或函数是依赖具体类实例的,那么就应该声明为实例的; 如果变量或函数不依赖于任何类实例,那么就应该声明为静态的。 例如:每个圆都有自己的半径值,半径依赖于具体的圆,因此将radius声明为Circle类的一个实例变量。而numberOfObjects不依赖于任何

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

最新文档

评论

0/150

提交评论