第5章 类和对象2Word文档下载推荐.docx
《第5章 类和对象2Word文档下载推荐.docx》由会员分享,可在线阅读,更多相关《第5章 类和对象2Word文档下载推荐.docx(17页珍藏版)》请在冰豆网上搜索。
inta,b,c;
staticintn;
2.静态数据成员是静态存储的,必须进行初始化。
格式:
数据类型类名:
:
静态数据成员名=值;
intNclass:
:
n=10;
3.静态数据成员不专属于任何一个对象,属于类。
如果访问权限允许的话(public),访问时可用:
类名:
静态数据成员名
例5.14
classMyclass
{public:
Myclass(inta,intb,intc;
voidGetNumber(;
voidGetSum(;
intA,B,C;
staticintSum;
//静态数据成员说明
};
intMyclass:
Sum=0;
//静态数据成员初始化
Myclass:
Myclass(inta,intb,intc
{数据成员2(参数,
……
{
<
”Number=”
TDate3:
TDate3(inty,intm,intd”
{”<
”cout<
”:
Constructorcalled.\n”;
}
可以:
TDate3(inty,intm,intd:
year(y,month(m,day(d
Sum={cout<
”:
Constructorcalled.\n”
例
M.GetNumber(;
N.GetNumber(;
M.GetSum(;
N.GetSum(;
A(intx:
a(x{}
Number=3,7,
classB
Number=14
B(intx,inty:
aa(x,b(y{}
Sum=54
Sum=54”aa=
例5.15
classCount
public:
Count({};
voidShows
输出:
aa=3
b=5
以上不能:
staticintsum;
{aa.a=x;
b=y;
}
intCount:
sum=100;
voidmain(
{Countc1;
c1.Showsum(;
5.3.3拷贝初始化构造函数
c4.Showsum(;
功能:
拷贝初始化构造函数名(const类名&
引用名Showsum(
sum的。
要输出
只能通过某个对象来调用函数Showsum(
3.如果类中没有说明拷贝初始化构造函数,则系统自动生成一个缺省拷贝初始化构造函数。
例5.9
5.5.2
//tpoint1.h
为了解决这个问题,如果
TPoint(intx,inty{X=x;
Y=y;
}了
TPoint(TPoint&
p;
sum;
编译错误。
因为对普通成员函数的调用必须通过对象名。
{cout<
采用静态成员函数来解决上述问题。
intXcoord({returnX;
intYcoord({returnY;
}public:
Count({intX,Y;
TPoint:
p
{X=p.X;
sum++;
”Copy_initializationConstructorCalled.\n”;
{cout<
”tpoint1.h”staticintsum;
{P2=”<
”,
Copy_initializationConstructorCalled.
100
5.10拷贝初始化构造函数的其他用法。
”tpoint1.h
1.TPointf(TPointQ;
关键字声明的成员函数。
2.同静态数据成员一样,静态成员函数属于整个类,为所有对象所共享。
P(0,0;
对于公有的静态成员函数,可以通过类名或对象名来调用;
而一般的非静态成员函数只能通过对象名来调用。
P=f(N;
”P=”
静态成员函数可以直接访问该类的静态数据和函数成员;
而访问非静态数据成员,必须通过参数传递方式得到对象名,然后通过对象名来访问。
举例说明:
例5.17
”
staticvoidf1(Mm;
intx,y;
intA;
staticintB;
voidM:
f1(Mm
"
B="
B<
直接
Ok
释放对象Q
DestructorCalled.释放匿名对象
P=30,55
DestructorCalled.
A=5
B=15DestructorCalled.释放对象P
DestructorCalled.释放对象M
例5.18王婆卖西瓜。
每卖一个瓜,计算出该瓜的重量、总重量、总个数,还允许退瓜。
1.明确表示由一个对象初始化另一个对象。
classWatermelon
2.
P=f(N;
3.当对象作为函数返回值时。
系统用返回值初始化一个匿名对象时使用了拷贝初始化构造函。
returnR;
total_number++;
5.4成员函数的特性
~Watermelon(
一般成员函数
voiddisplay(;
特殊成员函数
floatweight;
5.4.1内联函数和外联函数
内联函数:
定义在类体内的成员函数。
外联函数:
说明在类体内,定义在类体外的成员函数。
intWatermelon:
total_number=0;
voidWatermelon:
display(
例5.11
classA
A(intx,inty{X=x;
}内联函数
inta({returnX;
}内联函数
”Totalweightis:
intX,Y;
inlineintA:
c(
Watermelonw1(3.5;
Watermelon:
total_disp(;
Watermelonw2(4.5;
Watermelonw3(5.6;
w3.display(;
d(return:
8
5.4.2
5.
classM
M(intx,inty{X=x;
M(intx{X=x;
Y=x*x;
intAdd(intx,inty;
intAdd(intx;
5.6.1友元函数
intXout({returnX;
intYout({returnY;
{
{X=x;
Y=y;
returnX+Y;
intM:
Add(intx
{X=Y=x;
Add(
{returnX+Y;
”a=”<
”<
””
doublegetx({returnx;
doublegety({returny;
doublex,y;
doubledistance(Point&
a,Point&
30
{doubledx=a.getx(-b.getx(;
doubledy=a.gety(-b.gety(;
returnsqrt(dx*dx+dy*dy;
{Pointp1(3.0,4.0,p2(6.0,8.0;
p1.Getxy(;
p2.Getxy(;
”Distanceis”<
distance(p1,p2
(3.0,4.0
(6.0,8.0
Distanceis5
分析:
disntance(这个函数是一个普通函数,如果想访问类的私有成员,必须通过类的接口函数getx(和gety(来实现。
成员函数多次调用,由于参数传递、类型检查和安全性检查需要时间开销,程序的运行效率不高。
有没有办法使类外的函数直接访问私有数据成员呢?
有,使用友元函数。
例5.20使用友元函数。
classPoint
Point(doublem,doublen{x=m;
y=n;
voidGetxy(
”(“<
”,”<
frienddoubledistance(Point&
a,
Point&
b;
b{doubledx=a.x-b.x;
doubledy=a.y-b.y;
友元函数的特点:
1.友元函数是普通函数,不是成员函数。
2.友元函数在调用时可以直接调用,不需要对象表示。
3.说明在类体内,说明时前加关键字friend。
4.定义在类体外,定义方法和普通函数一样。
5.它可以直接引用类中的私有成员。
通过友元的方式,一个普通函数可以访问到封装于某一类中的数据,这相当于给类的封装挖了一个小小的孔,把数据的隐藏掀开了一个小小的角,通过它,可以看到类内部的一些属性。
从这个角度讲,友元是对数据隐藏和封装的破坏。
但是考虑到数据共享的必要性,为了提高程序的效率,很多情况下,这种小的破坏也是必要的。
例5.21
classTime
Time(inth,intm
{hours=h;
minutes=m;
friendvoidTime12(Timetime;
friendvoidTime24(Timetime;
inthours,minutes;
voidTime12(Timetime
{if(time.hours>
12
{time.hours-=12;
”PM”<
else
”AM”<
voidTime24(Timetime
{TimeTime1(20,30,Time2(10,45;
Time12(Time1;
Time24(Time1;
Time12(Time2;
Time24(Time2;
8:
30PM
20:
10:
45AM
45
在本例中,友元函数是一个普通函数,同样,这个函数也可以是另外一个类的成员函数。
5.6.2友元类
同函数一样,类也可以声明为另一个类的友元,这时称为友元类。
若A类为B类的友元类,则A类的所有成员都是B类的友元函数,都可以访问B类的私有和保护成员。
例5.22分析下列程序的输出结果:
classX
{friendclassY;
//Y类是X类的友元类
voidSet(inti{x=i;
voidDisplay(
”x=”<
”,y=”<
intx;
staticinty;
classY
Y(inti,intj
{a.x=i;
X:
y=j;
”,y=”<
Xa;
intX:
y=1;
{Xb;
b.Set(5;
b.Display(;
Yc(6,9;
c.Display(;
x=5,y=1
x=6,y=9
x=5,y=9
说明:
1.一般来说,在一个类的成员函数中,不能引用另一个类的私有成员,但在友元类中可以。
2.X类的y是静态成员,通过Y类的对象c改变了它的值后,将仍然保存其值,在X类的对象b中,y成员的值仍然是改变后的值。
可见,Y类对象与X类对象共用静态成员y。
注意:
1.友元关系不能传递。
B类是A类的友元,C类是B类的友元,C类和A类之间,如果没有声明,就没有任何关系,不能进行数据共享。
2.友元关系是单向的。
B类是A类的友元,B类的成员函数可以访问A类的私有和保护数据,但A类的成员函数却不能访问B类的私有和保护数据。
5.7类的作用域
类的作用域(类域:
类的定义中由一对花括号括起来的部分。
在类域中定义的变量不能使用auto,register和extern等修饰符。
类域包含在文件域中。
5.8局部类和嵌套类
5.8.1局部类
局部类:
在一个函数体内定义的类。
inta;
{staticints;
classA;
voidinit(inti{s=i;
Am;
m.init(10;
5.8.2嵌套类
嵌套类:
在一个类中定义的类。
…
voidf(;
5.9对象的生存期
对象的生存期:
指对象从被创建到被释放为止的时间。
按生存期可分:
1.局部对象:
当对象被定义时调用构造函数,当程序退出定义该对象所在的函数体或程序块时,释放对象。
2.静态对象:
当程序第一次执行所定义的静态对象时,该对象被创建,当程序结束时,该对象被释放。
3.全局对象:
当程序开始时,调用构造函数创建对象,当程序结束时,该对象被释放。
局部对象定义在函数体或程序块内。
静态对象定义在一个文件中。
全局对象定义在某个文件中。
例5.23不同对象的生存期
A(char*st
{strcpy(string,st;
”Constructorcalledfor”
~A(
”Destructorcalledfor”
charstring[50];
{AFunObject(“FunObject”;
局部对象
staticAstaticObject(“StaticObject”;
静态对象
”Infun(.”<
AGlobalObject(“GlobalObject”;
全局对象
{AMainObject(“MainObject”;
”Inmain(,beforcalledfun\n”;
”Inmain(,aftercalledfun\n”;
ConstructorcalledforGlobalObject
ConstructorcalledforMainObject
Inmain(,beforcalledfun
ConstructorcalledforFunObject
ConstructorcalledforStaticObject
Infun(.
DestructorcalledforFunObject
Inmain(,aftercalledfun
DestructorcalledforMainObject
DestructorcalledforStaticObject
DestructorcalledforGlobalObject
作业:
1.设立一个立方体类Box,在该类定义中包括:
数据成员:
length,width和height。
成员函数:
(1Box(设置盒子的长、宽和高;
(2volume(计算盒子的体积;
(3area(计算盒子的表面积;
(4disp(输出盒子的体积和表面积。
在main(中创建对象,求盒子的体积和表面积,输出体积和表面积。
2.定义一个Book类,在该类定义中包括:
bookname,price和number;
(1Book(为对象赋初值。
(2display(显示图书的情况。
3.遍写一个程序,输入N个学生数据,包括学号、姓名、成绩、要求输出这些学生数据并计算平均分。
4.第5章后面的作业题四。
练习:
第5章后面的练习题和作业题一、二、三。