版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
1、第六章 静态友元与运算符重载,静态成员 友元 运算符重载,1. 静态成员,静态成员 它主要解决同一个类的不同对象之间的共享问题。 在说明类成员(数据成员和成员函数)时,如果用了static关键字,则这类成员称为类的静态成员。 分为:公有(类外部访问);私有、保护(类内部访问) 如: class Date int year, month, day; static int count;/日期个数 静态数据成员 public: static void showCount();/显示日期个数 静态成员函数 Date(int y,int m,int d); void print() const ; ;/
2、-,静态数据成员 静态成员可以实现多个同类对象的数据共享,它不是某一个对象的成员。 静态数据成员只存储一处,供所有对象使用。 静态数据成员具有静态生存期,它的内存空间在编译阶段就已经分配,程序结束时释放。 共享包括: 变化的共享-如类对象创建的计数值。 不变的共享-如日期类中可能使用到的12个月的名称, 它是一个静态数组。最好设置为const。 如:static const char* monArr12; 这些共享数据是专属于某个类的变量。,/file Date.h #ifndef DATE_H #define DATE_H #include using namespace std; clas
3、s Date int year, month, day; public: /静态数据成员 static int count; Date(int y,int m,int d); void print() const ; ; #endif /file Date.cpp #include Date.h / 静态数据成员初始化 int Date:count=0; Date:Date(int y,int m,int d) count+; year=y; month=m; day=d; ,void Date:print()const coutyear- month- dayn; /file Main.cp
4、p #include Date.h void main() Date d1(2007,1,12); Date d2(2007,2,12); / 可行,但非标准 coutd1.countn; / 标准 访问静态成员 coutDate:countn; ,2 2,静态成员函数 当一个成员函数被说明为static时,它是静态成员函数。 静态成员函数不与特定的对象关联,为所有类的对象共享。 调用静态成员函数的格式如下: .() 或 :(),/file Date.h #ifndef DATE_H #define DATE_H #include using namespace std; class Date
5、 int year, month, day; static int count; public: static void showCount(); Date(int y,int m,int d); void print() const ; ; #endif /file Date.cpp #include Date.h / 静态数据成员初始化 int Date:count=0; Date:Date(int y,int m,int d) count+; year=y; month=m; day=d; ,void Date:print()const coutyear- month- dayn; vo
6、id Date:showCount() / 访问静态私有成员 cout当前日期个数: count个n; /file Main.cpp #include Date.h void main() Date d1(2007,1,12); Date d2(2007,2,12); / 可行,但非标准 d1.showCount(); / 标准 静态成员函数调用 Date:showCount(); ,当前日期个数:2个 当前日期个数:2个,一般成员函数与静态成员函数的区别: 一般成员函数:主要用来对类对象的数据成员进行操作。 每个类的对象有自己的数据成员,但类中的成员函数只有一份,因此调用成员函数时必须指明是
7、对那个类对象操作。 确定类对象:通过一个叫 this指针的隐含参数来完成的。,void Date:print() const coutyearmonthdayn; ,void Date:print() const coutyear- month- dayn; ,等价于,void main() Date d1(2007,1,12); Date d2(2007,2,12); d1.print(); /把对象d1的地址传递给this指针 d2.print(); /把对象d2的地址传递给this指针 ,静态成员函数:不与特定的对象关联,为所有类的对象共享。 静态数据成员:也为类的所有对象共享,所以在静
8、态成员函数的实现中,可以直接引用静态数据成员。如: void Date:showCount() cout“当前日期个数:”count“个n”; / 访问静态数据 ,无法直接操作非静态数据成员: 原因:静态成员函数无this指针。无this指针导致编译程序无法确定静态成员函数中操作的非静态数据成员到底属于哪个对象。所以不能直接操作。 举例: void Date:showCount() cout“当前日期个数:”count“个n”; / 访问静态数据 coutyearendl;/访问非静态数据 解决方法:在定义静态成员函数时,设置一个对象形参,调用静态成员函数时将相应的对象传递给静态成员函数。当然
9、也可以在函数中新定义对象。,/file Date.h #ifndef DATE_H #define DATE_H #include using namespace std; class Date int year, month, day; static int count; public: static void showCount(Date ,void Date:print()const coutyear- month- dayn; void Date:showCount(Date ,当前日期个数:2个 参数传入的日期:2007-2-12,2.友 元,一个类的私有数据和函数只能在类的作用域中
10、使用,程序中的对象是无法直接访问一个类中的私有成员的。 类的这种封装性使得对数据的访问提供了安全性,同时也带来了某些不便。 因此,需要寻求一种途径,使得类以外的对象和函数能够直接访问类中的私有成员。 在C+中,友元便是实现这个要求的一个辅助手段。 友元可以是一个函数,该函数称为友元函数;也可以是一个类,该类称为友元类。,友元函数 首先,它是一般的函数,而不是类的成员函数; 其次,在类的定义中,用friend关键字将它说明为类的友元(在私有段和公有段都可),这样它被允许可访问该类的所有对象的私有成员。 优点:友元可以直接访问对象的私有成员,省去了调用类成员函数的开销。提高了程序的效率。 缺点:破
11、坏了类的封装性和隐藏性,使得非成员函数可以访问类的私有成员。导致程序的可维护性差。,/file Point.h #ifndef POINT_H #define POINT_H #include #include using namespace std; class Point /声明友元函数 friend double dist(Point vp1,Point vp2); int x,y; public: Point (int a=0,int b=0) x=a;y=b; ; #endif /file Point.cpp #include Point.h double dist(Point vp
12、1, Point vp2) int dx,dy; dx=vp1.x-vp2.x; dy=vp1.y-vp2.y; return sqrt(dx*dx+dy*dy); ,/file Main.cpp #include Point.h void main() Point p1 (1,1) , p2 (3,3); double d=dist(p1,p2); /d=p1.dist(p1,p2);是错误的 coutdist=d endl; ,dist=2.82843,友元类 一个类B 可以是另一个类A的友元。这意味着类B 中的所有成员函数都可以访问类A中的私有成员。 说明类B 是类A的友元的方法是在类A
13、中加入说明语句:friend class B ; 即A主动说明B够朋友 此语句所在的位置没有特别的要求,在公有和私有段都可。 友元关系不能传递。 函数F类B(F是朋友)类A(B是朋友),/file A.h #ifndef A_H #define A_H #include using namespace std; const int MaxSize=10; class A friend class B; int x; public: A(int vx=0)x=vx; ; #endif /file B.h #ifndef B_H #define B_H #include A.h class B A
14、 arrMaxSize; int number; public: B()number=0; int Sum(); void Add(const A #endif,/file B.cpp #include B.h void B:Add(const A ,/file Main.cpp #include B.h #include A.h void main() A oa1(10); A oa2(50); A oa3(40); B ob; ob.Add(oa1); ob.Add(oa2); ob.Add(oa3); cout和=ob.Sum(); ,和=100,/file Car.h #ifndef
15、CAR_H #define CAR_H #include Truck.h #include using namespace std; /将类名通知编译器, /说明类Truck存在 class Truck; class Car private: int speed; public: Car(int s); friend int sp(Car c,Truck t); ; #endif /file Car.cpp #include Car.h Car:Car(int s) speed=s; ,/file Truck.h #ifndef TRUCK_H #define TRUCK_H #include
16、 Car.h /将类名通知编译器, /说明类Car存在 class Car; class Truck private: int speed; public: Truck(int s); friend int sp(Car c,Truck t); ; #endif,友元应用举例 多个类的共同朋友,/file Truck.cpp #include Truck.h Truck:Truck(int s) speed=s; ,/file Main.cpp #include Car.h #include Truck.h int sp(Car c,Truck t); void main() Car c1 (
17、140); Truck t1 (90); int t=sp(c1,t1); cout t=tendl; int sp(Car c,Truck t) return c.speed-t.speed; ,t=50,3. 运算符重载,运算符重载的作用是什么? 所谓运算符重载就是赋予已有的运算符多重含义。 C+中预定义的运算符其运算类型只能是基本数据类型,而不适用于用户自定义类型(如类)。 运算符重载使运算符的运算对象扩充为自定义类型(如类) 。 int x,y,z; z=x+y; class Point private: int x,y; public: / ; Point p1,p2,p3; p3=
18、p1+p2;,哪些运算符可以用作重载? 几乎所有的运算符都可用作重载。 这些运算符不允许重载: . : ?: sizeof 重载运算符有哪些限制? 不可臆造新的运算符。必须把重载运算符限制在C+语言中已有的运算符范围内的允许重载的运算符之中。 重载运算符坚持4个不能改变 。 不能改变运算符操作数的个数; 不能改变运算符原有的优先级; 不能改变运算符原有的结合性; 不能改变运算符原有的语法结构。 运算符重载时必须遵循哪些原则? 使用重载运算符时应遵循如下原则:(1) 重载运算符含义必须清楚。(2) 重载运算符不能有二义性。,运算符重载的两种形式 运算符重载的函数一般地采用如下两种形式:成员函数形
19、式和友元函数形式。这两种形式都可访问类中的私有成员。 重载为成员函数,/file Point.h #ifndef POINT_H #define POINT_H #include using namespace std; class Point int x,y; public: Point(int vx=0,int vy=0) x=vx;y=vy; Point operator+(const Point #endif,/file Point.cpp #include Point.h Point Point:operator+(const Point ,p3=p1+p2 被编译程序解释为:p3=
20、 p1.operator+(p2),重载为友元函数,/file Point.h #ifndef POINT_H #define POINT_H #include using namespace std; class Point int x,y; public: Point(int vx=0,int vy=0) x=vx;y=vy; void print() coutx,yn; friend Point operator+(const Point #endif,/file Point.cpp #include Point.h Point operator +(const Point ,P3=p1
21、+p2 被编译程序解释为p3= operator+(p1, p2),总结 一般说来,单目运算符最好被重载为成员函数; 对双目运算符最好被重载为友元函数。 双目运算符重载为友元函数比重载为成员函数更方便些。,运算符重载举例,1.下标运算符重载 ,下面的类Vector中定义了一个私有的数组成员,要想访问数组中的某个元素,习惯上是使用下标比较直观(如Vector4),但由于类的封装性,不可能访问到这样的细节。可以通过重载下标运算符 来实现。,/file Vector.h #ifndef VECTOR_H #define VECTOR_H #include using namespace std; c
22、lass Vector int length ; int *arr; public: Vector(int len); Vector(); void Print(); void Add(int value); /返回当前下标所指数组元素 int #endif,/file Vector.cpp #include Vector.h Vector : Vector(int len) arr=new intlen; if (arr=NULL) exit(1); length=0; Vector : Vector() if (arr!=NULL) delete arr; arr=NULL; void V
23、ector :Print() coutn数组元素:; for(int i=0;ilength;i+) coutarri ; ,void Vector :Add(int value) arrlength+=value; int ,请连续输入5个整数 11 12 13 14 15 数组元素:11 12 13 14 15 修改后的50 数组元素:11 12 13 50 15,动态申请二维空间 int row,col ; int *arr; arr=new int*row;/动态分配行 /为每一行分配列空间 for(int i=0;irow;i+) arri=new intcol;,arr,行,列,2
24、 重载输入运算符 和输出运算符”可以实现实现用户自定义类型的输入输出:,/file Complex.h #ifndef COMPLEX_H #define COMPLEX _H #include using namespace std; class Complex float real,imag; public: Complex(float r,float i)real=r; imag=i; Complex()real=0;imag=0; friend ostream #endif,/file Complex.cpp #include Complex.h ostream ,/file Main
25、.cpp #include Complex.h void main() Complex c1(2.3f,4.6f),c2(3.6f,-9.8f),c3,c4; coutc3c4; /等价于? coutc3、c4的值分别是:endl; coutc3c4; ,c1、c2的值分别是: 2.3+4.6i 3.6-9.8i Input the real,imag of the complex: 2 3 Input the real,imag of the complex: 5 6 c3、c4的值分别是: 2+3i 5+6i,3 赋值运算符重载(=) 对象赋值即对象拷贝:两个已经存在的对象之间的复制 Po
26、int p1, p2(1,4); p1= p2; / 对象赋值 对象赋值便是使用类中的赋值操作符 如果类中没有定义赋值操作符,则系统悄悄地定义一个默认的赋值操作符: Point 当对象中没有动态堆内存时,以上默认赋值操作符可以胜任; 当对象中存在动态堆内存时,则对象赋值操作符必须自定义。,/file Person.h #ifndef PERSON_H #define PERSON _H #include using namespace std; class Person public: Person(char* pN); Person(const Person #endif,调用缺省赋值函数,/file Person.cpp #include Person.h Person:Person(char* pN) pName=new charstrlen(pN)+1; if(pName!=0) strcpy(pName,pN); coutthis Constructing pNameendl; Person:Person(const Person ,Person:Person() coutthis Destructing pName endl; if(pName) delete pName
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 初中美术阅读教案设计
- 建筑工程测量技术实务指导
- 超市员工培训总结
- 陶瓷材料技术行业标准解读与应用
- 五年级英语上学期期中测试真题
- 行政审批流程优化实施报告
- 工程造价管理实务与风险控制案例
- 行政能力培训
- 厉行节约制止餐饮浪费管理制度
- 行政培训计划方案
- 中建技术总工(技术负责人)竞聘报告
- DLT 573-2021电力变压器检修导则-PDF解密
- 《浙江省安装工程预算定额》(2010版)
- 东方铸造行业分析
- 财务会计核算制度范本
- 在C51单片机上对读写卡芯片MFRC522编程
- 《西游记》电子版阅读-小学版
- 2024年全年日历表带农历(A4可编辑可直接打印)预留备注位置 精心整理
- TISCO二期扩建工程项目总承包(EPC)合同 中英文
- 磷酸钠安全周知卡、职业危害告知卡、理化特性表
- 你的名字钢琴谱简谱
评论
0/150
提交评论