【文档说明】第6章面向对象的妥协课件.ppt,共(36)页,218.023 KB,由小橙橙上传
转载请保留链接:https://www.ichengzhen.cn/view-44844.html
以下为本文档部分文字说明:
第6章面向对象的妥协授课内容6.1封装的破坏——友元6.2对象机制的破坏——静态成员6.1封装的破坏——友元6.1封装的破坏——友元友元可以访问与其有好友关系的类中的任何成员。友元友元函数友元类如果在本类以外的其他地方定义了一个函数(这个函数可以是不属于任何类的普通函数,也可以是
其他类的成员函数),在类体中用friend对其进行声明,此函数就称为本类的友元函数。友元函数可以访问这个类中的任何成员。如何将普通函数声明为友元函数呢?看下面这个简单的例子:§6.1封装的破坏——友元6.1.1友元函数
【例6-1】友元普通函数。#include<iostream>usingnamespacestd;classClock//声明Clock类{public:Clock(int,int,int);friendvoiddisplay(Clock&);priva
te:inthour;intminute;intsecond;};§6.1.1友元函数【例6-1】友元普通函数。#include<iostream>usingnamespacestd;classClock//声明Clock类{public:
Clock(int,int,int);friendvoiddisplay(Clock&);private:inthour;intminute;intsecond;};【例6-1】友元普通函数。Clock::Clock(inth,intm,ints)//构造函数{hour=h;minu
te=m;second=s;}//这是友元函数,形参t是Clock类对象的引用voiddisplay(Clock&t){cout<<t.hour<<":"<<t.minute<<":"<<t.second<<endl;}in
tmain(){Clockt(10,13,56);display(t);//调用display函数,实参t是Clock类对象return0;}§6.1友元函数程序运行结果如下:10:13:56cout<<hou
r<<":"<<minute<<":"<<second<<endl;注意§6.1.1友元函数#include<iostream>usingnamespacestd;classDate;//对Date类的提前引
用声明classClock//声明Clock类{public:Clock(int,int,int);voiddisplay(Date&);private:inthour,minute,second;};【例6-2】友元成员函数。
classDate//声明Date类{public:Date(int,int,int);friendvoidClock::display(Date&);private:intmonth;intday;intyear;};§6.1.1友元函数Clock::Clock(in
th,intm,ints)//Clock类的构造函数{hour=h;minute=m;second=s;}voidClock::display(Date&dd){cout<<dd.month<<"/"<<dd.day<<"/"<<dd.year<<endl;co
ut<<hour<<":"<<minute<<":"<<second<<endl;}Date::Date(intm,intd,inty)//Date类的构造函数{month=m;day=d;year=y;}§6.1.1友元函数intmain(){Clockt(10,13,56)
;//定义Clock类对象tDated(12,25,2004);//定义Date类对象d//调用t的display函数,实参是Date类对象dt.display(d);return0;}§6.1友元函数程序运行结果如下:12
/25/200410:13:56不仅可以将一个函数声明为一个类的“朋友”,而且可以将一个类(例如B类)声明为另一个类(例如A类)的“朋友”。这时B类就是A类的友元类。友元类B中的所有成员函数都是A类的友元函数,可以访问
A类中的任何成员。§6.1封装的破坏——友元6.1.2友元类classstudent;classTeacher{public:voidassigngrades(Student&s);//给出学生成绩protected:intstu_count;//学生人数Stud
ent*plist[100];//学生数组};§6.1.2友元类classStudent{public:friendTeacher;//友元类…protected:intnum;stringname;floatscore;};…§6.1.2友元类声明友元类的一般形式为:f
riend类名;关于友元,有三点需要说明:(1)友元函数的声明可以出现在类的任何地方(包括在private和public部分),也就是说友元的说明不受成员访问控制符的限制。§6.1.2友元类(2)友元关系是单向的而不是双向的,如果声明了B类是A类的友元类,不等于A类是B类的友元类
,A类中的成员函数不一定能够访问B类中的成员(3)友元关系是不能传递的,例如,如果B类是A类的友元类,C类是B类的友元类,并不能说C类就是A类的友元类。6.1对象机制的破坏——静态成员在C++中,
声明了一个类之后,可以定义该类的多个对象。系统为每个对象分配单独的内存空间。每一个对象都分别有自己的数据成员,不同对象的数据成员各自有其值,互不相干。但是有时我们希望有某一个或几个数据成员为所有对象所共有。这样可以实现数据共享。§6.2对象
机制的破坏——静态成员我们知道全局变量能够实现数据共享。但是用全局变量的安全性得不到保证,因为在各处都可以自由地修改全局变量的值,很有可能由于某个没注意到的失误,全局变量的值就被修改,导致程序的失败。因此在实际工作中很少使用全局变量。如果想在
同类的多个对象之间实现数据共享,也不要用全局对象,可以用静态成员。静态成员包括静态数据成员和静态成员函数。§6.2对象机制的破坏——静态成员静态数据成员是一种特殊的数据成员。它以关键字static开头
。例如:§6.2对象机制的破坏——静态成员6.2.1静态数据成员classStudent{public:Student(char*name="noname");staticintstu_count;charname[40];};静态数据成员在内存中只占一份空间(而不是每个对象都分别为
它保留一份空间),它是属于类的,但它被该类的所有对象所共享,每个对象都可以访问这个静态数据成员。静态数据成员的值对所有对象都是一样的。如果改变它的值,则在各对象中这个数据成员的值都同时改变了。这样可以节
约空间,提高效率。§6.2.1静态数据成员说明:(1)如果只声明了类而未定义对象,则类的一般数据成员是不占内存空间的,只有在定义对象时,才为对象的数据成员分配空间。但是静态数据成员不属于某一个对象,在为对象所分配的空间中不包括静态数据成员所占的空间。静态数据成员是在所有对象之外单
独开辟空间。只要在类中定义了静态数据成员,即使不定义对象,也为静态数据成员分配空间,它可以被访问。在一个类中可以有一个或多个静态数据成员,所有的对象共享这些静态数据成员,都可以访问它。§6.2.1静态数据成员(2)静态数据成员不随对象的建立而分配空间,也不随对象的撤
销而释放(一般数据成员是在对象建立时分配空间,在对象撤销时释放)。静态数据成员是在程序编译时被分配空间的,到程序结束时才释放空间。§6.2.1静态数据成员(3)静态数据成员可以初始化,但只能在类体外进行初始化。如:intStudent::stu_count=0;//表示对Student类中的静
态数据成员初始化静态数据成员可以初始化语句的一般形式为:数据类型类名::静态数据成员名=初值;不必在初始化语句中加static。§6.2.1静态数据成员(4)静态数据成员既可以通过对象名访问,也可以通过类名来访问。§6.2.1静态数据成员【例6-3】
访问静态数据成员。#include<iostream>usingnamespacestd;#include<string>classStudent{public:Student(char*name="noname");~Stude
nt();staticintstu_count;charname[40];};§6.2.1静态数据成员【例6-3】访问静态数据成员。#include<iostream>usingnamespacestd
;#include<string>classStudent{public:Student(char*name="noname");~Student();staticintstu_count;charname[40];};Studen
t::Student(char*pname){strcpy(name,pname);stu_count++;//每创建一个对象,学生人数加1}Student::~Student(){stu_count--;
//每释放一个对象,学生人数减1}//对静态数据成员stu_count初始化intStudent::stu_count=0;§6.2.1静态数据成员intmain(){Students1;cout<<s1.st
u_count<<endl;{Students2;cout<<s2.stu_count<<endl;}cout<<Student::stu_count<<endl;return0;}程序运行结果如下:121§6.2.1静态数据成员与静态数据成员不同,静态成员函数的作用不是为了对象之
间的沟通,而是为了能处理静态数据成员。§6.2对象机制的破坏——静态成员6.2.2静态成员函数【例6-4】静态成员函数访问静态数据成员的例子。#include<iostream>usingnamespacestd;#include<string>cl
assStudent//声明Student类{public:Student(char*name="noname");~Student();staticintgetcount(){returnstu_coun
t;}private:staticintstu_count;charname[40];};§6.2.2静态成员函数Student::Student(char*pname){strcpy(name,pname);stu_count++;//每创建一个对象,学生人数加1}Stude
nt::~Student(){stu_count--;}//每销毁一个对象,学生人数减1intStudent::stu_count=0;§6.2.2静态成员函数intmain(){Students1;cout<<s1.getcount()<<endl;{Students2;cout
<<s2.getcount()<<endl;}cout<<Student::getcount()<<endl;return0;}§6.2.2静态成员函数§6.2.2静态成员函数和静态数据成员一样,静态成员函数是类的一部分,而不是对象的一部分。如果要在类外调用公用的静态成员函数,可以用类名和域
运算符“::”,也允许通过对象名调用静态成员函数。如:Student::getcount();//用类名调用静态成员函数s1.getcount();//用对象名调用静态成员函数但这并不意味着此函数是属于
对象s1的,而只是用s1的类型而已。§6.2.2静态成员函数说明:(1)静态成员函数不能默认访问本类中的非静态成员。当调用一个对象的成员函数(非静态成员函数)时,系统会把该对象的起始地址赋给成员函数的this指针。而静态成员函数并不属于某一对象,它与任何对象都无关,因此静态成员函数没有this
指针。既然它没有指向某一对象,就无法对一个对象中的非静态成员进行默认访问(即在访问数据成员时不指定对象名)。可以说,静态成员函数与非静态成员函数的根本区别是:非静态成员函数有this指针,而静态成员函数没有this指针,因而决定了
静态成员函数不能默认访问本类中的非静态成员。§6.2.2静态成员函数说明:(2)静态成员函数可以直接访问本类中的静态数据成员,因为静态成员同样是属于类的,可以直接访问。在C++程序中,静态成员函数主要用来访问静态数据成员,而不访问非静态成员。假如在一个静态成员函数中有以下语句:cout<
<age<<endl;//若age已声明为static,则访问本类中的静态成员,合法cout<<score<<endl;//若score是非静态数据成员,不合法§6.2.2静态成员函数说明:但是,并不是绝对不能访问本类中的非静态成员,只是不能进行默认访问,因为无法知道应该去找哪个对象。如
果一定要访问本类的非静态成员,应该加对象名和成员运算符“.”。如静态成员函数中可以出现:cout<<s.score<<endl;这里假设s已定义为Student类对象,且在当前作用域内有效,则此语句合法。§6.2.2静态成员函数但是在C++程序中最好养成这样的
习惯:只用静态成员函数访问静态数据成员,而不访问非静态数据成员。这样思路清晰,逻辑清楚,不易出错。