类的运算符重载.docx_第1页
类的运算符重载.docx_第2页
类的运算符重载.docx_第3页
类的运算符重载.docx_第4页
类的运算符重载.docx_第5页
已阅读5页,还剩15页未读 继续免费阅读

下载本文档

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

文档简介

类的运算符重载 参考书籍 :C+ 世界的两本世界名著 C+ 程序设计语言 和 C+primer重载知识点 1. 重载运算符 1.1 引言 1.2 限定及重载语法 1.2.1 限定 1.2.2 重载语法 1.3 重载运算符设计指导 1.4 成员 / 非成员函数重载 1.5 成员函数重载 1.6 非成员函数 ( 友元函数 ) 重载 1.7 重载实例 1.7.1 重载输入输出符 1.7.2 重载算法运算符 +,-1.7.3 重载关系运算符 =,!=,=,=1.7.4 重载赋值运算符 =1.7.5 重载下标结算符 1.7.6 重载前置自增 +, 自减 - 和重载后置自增 +, 自减 -1.7.7 重载成员访问符 - 和 *1.7.8 重载调用操作符 ()1.7.9 重载转换操作符 operator (type) *1 前言 重载运算符目的: 1. 用操作整数的各种运算方法 , 让运算符重载让类也具有整数的各种简单运算 2. 我们对类产生的对象进行非常方便的运算操作 , 让代码、简洁明了 , 操作方便 *2 定义 2.1 限定及重载语法 可以重载的运算符 + - * / % & | ! = += -= *= /= %= = &= |= = = = != = & | + - - * , () new delete new delete 不可以重载的运算符 : . .* ?: sizeof typeid 分类 算术运算符 + - * / % + -复合算术运算符 += -= *= /= %= =位运算符 & | ! 复合位运算符 &= |=逻辑运算符 & |关系运算符 = != = =内存管理符 new delete new delete 输入输出运算符 = * 2.2 定义 重载语法 语法 :returntype operator op( 类参数 )中文 : 返回类型 operator 运算符号 ( 参数 )例子: item operator+(const item&,const item&); * 2.3 成员函数实现操作符重载 使用情况:通常对类本身的运算符重载 如类 nameclass 的运算符函数名称 operator op如 x,y 都是类 nameclass 的生成的对象 , 如果重载并实现了 operator op我们可以做这样的计算 x op y, 编译器会自动翻译成如下 x.operator op(y)如 op 是重载的运算符是加法 (+), 那么可变成 x+y, 编译器会变成 x.operator+(y)计算顺序是: x op y 变成 x=x op y, 运算结果存入到 x,x.operator+(y)第一个操作数是类的对象 x, 也就是隐含的对象指针 this,第二个操作数是参数 y, 对象 X 与的数据成员逐个一一相加 ,返回结果 : 是计算完毕后返回到左边的对象 , 它返回的必须是对象 , 而不能是其它数据类型 . 重载下标 取值运算符实例 定义 operatorclass fooprivate:vector data;public:int& operator (const size_t); ;实现 operatorint& foo:operator(const size_t index) return dataindex; * 2.4 非成员函数 ( 友元函数 ) 实现操作符重载 使用情况:类的对象之间进行的算法运算符 , 关系运算符 , 输入输出 假设 # 是运算符号 类 nameclass 的友元函数重载名称 operator#如 x,y 都是类 nameclass 的生成的对象 , 如果重载并实现了友元函数 operator#我们可以做这样的计算 x # y, 编译器会自动翻译成如下 operator#(x,y)计算顺序是: x op y 变成 op(x,y), 运算结果存入到新的临时对象 ,operator+(x,y)绝对无对象指针 this, 返回值不会存入到 x,y, 而是返回新的临时对象 第一个操作数是类的对象 x,第二个操作数是参数 y,对象 X 与 Y 的数据成员逐个一一相加 ,返回结果 : 建立一个新的返回对象 , 如算术运算符返回另一个对象 , 关系运算符返回 bool 值 类的运算符重载的友元函数实现格式 友元函数定义格式 friend returntype operator op(const classname&,const classname&)const;友元函数实现格式 returntype operator op(const classname&,const classname&)/ 代码控制 return (values); * 3 重载实例 3 .1 重载输入输出符 3 .2 重载算法运算符 -,*,/,%,3 .3 重载关系运算符 =,!=3 .4 重载赋值运算符 =3 .5 重载下标结算符 3 .6 重载前置自增 +, 自减 - 和重载后置自增 +, 自减 -3 .7 重载成员访问符 - 和 *3 .8 重载调用操作符 ()3 .9 重载转换操作符 operator (type) * 3 .1 重载 当我们对一个类重载 运算符之后 , 就可以直接使用 coutx 两种简单的操作 a. 重载输出运算符 因重最左边的操作数是 ostream, 自然就不能用类的成员函数重载 , 而只能以类的友元函数进行重载 / 函数定义格式 friend ostream operator(ostream&,const nameclass&)const;/ 函数实现部分 ostream & operator因重最左边的操作数是 istream, 自然就不能用类的成员函数重载 , 而只能以类的友元函数进行重载 /(istream&,const nameclass&)const;/(istream& in,const classname& object)/local delcare if any/check object istream/output the members of the object/. return in; c. 代码实现 / 重载函数 定义 class OpOverpublic:OpOver(int i=0;int j=0)a=i;b=j;friend ostream& operator(istream&,const OpOver&);OpOver operator+(const OpOver&)const;bool operator=(const OpOver&)const;private:int a;int b;/ 重载函数 实现 ostream& operator(ostream& out,const OpOver& right)outright.a,(istream& in,const OpOver& right)inright.aright.b;return in; *3 .2 重载算法运算符 -,*,/,%, 当我们对一个类重载 +,- 运算符之后 , 就可以直接使用 x+y,x-y 两种简单对象之间的加减操作 1.7.2.1 重载 +因最左边的操作数是用类生成的新对象 , 自然重载 + 可以用成员函数也可以友元函数 /+ 重载函数用类的成员函数实现的定义格式 classname& operator+(const nameclass&,const nameclass&)const;/+ 重载函数用类的成员函数实现的实现格式 classname& classname:operator+(const classname& left,const classname& right)classname& tempclass(left); / 用左对象 left 建立一个新的对象 tempclasstempclass+=right; / 临时对象 tempclass 与 right 的各个数据成员一一相加 / 上面这个代码要还要细化 return tempclass; / 返回运算结果到 left 的另一个副本 tempclass 3 .2.1 算术运算符重载 -,*,/,%,如同上面重载加法运算符一样,非常简单 只要在定义和实现,把 + 改成相应的其它算术运算符号就行啦 在函数实现部分只要把两个对象的各个成员分别进行相应的算术运算就行啦, 然后返回计算结果的临时对象就 OK 啦 实例代码 class OpOverpublic:OpOver(int i=0;int j=0)a=i;b=j;OpOver& operator+(const OpOver&)const;OpOver& operator-(const OpOver&)const;OpOver& operator*(const OpOver&)const;OpOver& operator/(const OpOver&)const;OpOver& operator%(const OpOver&)const;private:int a;int b;/ 用类成员函数重载运算符 +OpOver& OpOver:operator+(OpOver& left,const OpOver& right)OpOver& tempclass(left); tempclass.a+=right.a;tempclass.b+=right.b;return tempclass;/ 用类成员函数重载运算符 -OpOver& OpOver:operator-(OpOver& left,const OpOver& right)OpOver& tempclass(left); tempclass.a-=right.a;tempclass.b-=right.b;return tempclass;/ 用类成员函数重载运算符 *OpOver& OpOver:operator*(OpOver& left,const OpOver& right)OpOver& tempclass(left); tempclass.a*=right.a;tempclass.b*=right.b;return tempclass;/ 用类成员函数重载运算符 /OpOver& operator/(OpOver& left,const OpOver& right)/ 要检查 right 的各个成员不能为 0if (right.a!=0 & right.b!=0 )OpOver& tempclass(left); tempclass.a/=right.a;tempclass.b/=right.b;return tempclass;/ 用类成员函数重载运算符 %OpOver& OpOver:operator%(OpOver& left,const OpOver& right)/ 要检查 right 的各个成员不能为 0if (right.a!=0 & right.b!=0 )OpOver& tempclass(left); tempclass.a%=right.a;tempclass.b%=right.b;return tempclass; * 3 .3 重载关系运算符 = , !=重载关系运算符的编码指导,当实现一个关系运算符时,最好也实现此关系运算的反运算, 如成对实现 = 和 != , 成队实现, = 成队实现 当我们对一个类重载 =,!= 关系运算符之后 , 就可以直接使用 x=y,x!=y 两种简单对象之间的关系运算判断操作 3 . 3 .1 重载 =关系运算之后的结果是 bool, 自然重载 =,!= 可以用成员函数也可以友元函数 = 重载函数用类的成员函数实现的定义格式 bool operator=(const nameclass&,const nameclass&)const;/+ 重载函数用类的成员函数实现的实现格式 bool classname:operator=(const classname& left,const classname& right)return (left. 成员 a=right. 成员 a & left. 成员 a=right. 成员 a & .); / 要比较两个对象之间所有的数据成员全部是否相等,结果相等返回 true, 不相等返回 false 代码实现 以上面的类 OpOver 为基础实现 = 重载关系运算 bool OpOver:operator=(const classname& left,const classname& right) return (left. 成员 a=right. 成员 a & left. 成员 a=right. 成员 a ); 以上面的类 OpOver 为基础实现 != 重载关系运算就更加简单,在 = 已经实现的基础上 实现重载 != 运算符的实现 bool OpOver:operator!=(const classname& left,const classname& right) return !(left=right); * 3 .4 重载赋值运算符 =它必须用类的成员函数来实现,而不能用友元函数 classname x,y;x 各成员得到数据,而 y 的数据成员是空的 .y=x, 就把对象 x 中所有成员的数据复制到 y 的对应的成员里面 要让一个类的产生的不同以象可以直接进行赋值,就得重载并实现 = 赋值运算符 一般定义语法: const classname& operator=(const classname&);一般实现语法: const classname& classname:operator=(const classname& other)/ 如果有局部变量,则定义 if(this!=other)/ 初始化 this 所指向的对象 / 复制 other 对象的所有成员的数据到 this 对象 else/ 如果 other 对象是空值,则直接把 this 对象置空 return *this; / 返回 this 指针所指向的引用对象 代码实例 class ilistpublic:ilist(int mszie=20);const ilist& operator=(const ilist&); / 重载 = 运算符 void clearlist();void print()const;void insertitem(int item);private:int maxsize,length,int *list; ilist:ilist(int msize)length=0;if (msize=20) maxsize=20;else maxsize=msize;list= new intmaxsize; assert(list!=NULL);const ilist& ilist:operator=(const ilist& other)/ 隐含使用 this 指针进行运算 if(this!=&other) if (list!=NULL) clearlist(); / 如果 this 所指的对象有数据,则清空它们 if (other.maxsize!=0) / 如果 other 引用的对象有数据,则复制它们到 this 指针指向的对象 list=new intother.maxsize; assert(list!=NULL); for(int i=0;i!=other.length,i+) listi =other.listi; elselist=NULL; return *this; * 3 .5 重载下标结算符 它必须用类的成员函数来实现,而不能用友元函数 按位置索引快速的访问容器类的单个元素,容器如 string, 数组, vector 等 重载下标运算符 设计方案 一般要实现两个 运算符,一个用于访问加上 const ,一个用于修改不加 const.定义 class demopublic:int& operator(const size_t); / 用于修改 const int& operator(const size_t)const; private:vector data;实现 int& demo:operator(const size_t index) return dataindex; const int& demo:operator(const size_t index)const return dataindex; * 3 .6 重载前置自增 +, 自减 - 和重载后置自增 +, 自减 -3 .6.1 引言 + , - 操作符经常用于迭代器这样的算法实现,在类中重载 + , - 后, 类就提供了如同指针行为的方式来访问类序列中的元素,带访问检查的指针类可以实现任意类型的数组 在 + , - 自然也仿照 int 运算,具有前置自增 +, 自减 - 和重载后置自增 +, 自减 -因编译器无法区分是前置还是后置, c+ 发明人就在后置 + , - 引入一个识别标记 (int) 1.7.6.2 如下面的类实现 +,- 的运算符 class checkedptrpublic: checkdptr(int* b,int* e):beg(b),end(e),curr(b) ;/ 定义前置 + , -checkdptr& operator+();checkdptr& operator+();/ 定义后置 + , - checkdptr operator+(int);checkdptr operator+(int);private:int* beg,int* end;int* curr; / 实现前置 + , -/ 表现形经常有 +x,-y ,它通常是先变量加 1 ,然后引用此变量 checkdptr& checkedptr:operator+()if(curr=end)throw out_of_ange( 超出访问办界 );curr+;return *this; checkdptr& checkedptr:operator-()if(curr=beg)throw out_of_ange( 超出访问办界 );curr-;return *this; / 实现后置 + , - , / 表现形经常有 x+,y- ,它通常是先引用此变量,然后变量加 1checkdptr checkedptr:operator+(int)checkedptr old(*this); / 用类生成对象 old, 用 this 指针的对象去初始 old,old 保存初值 +(*this); /this 指向的对象 +1return *old; / 返回调用 this 原来的初值 checkdptr checkedptr:operator-(int)checkedptr old(*this); / 用类生成对象 old, 用 this 指针的对象去初始 old,old 保存初值 -(*this); /this 指向的对象 -1return *old; / 返回调用 this 原来的初值 * 3 .7 重载成员访问符 - 和 *引言 为了让类支持指针操作,方便高效的操作类的对象,充许重载 * 和 - 两个操作符 * 常用用于构造智能指针, 1. 构建更安全的指针 用一个友元类来保存指针和使用计数,在 screenptr 最好一个对象消失后,自动删除基础对象 定义 scrptr 类 class scrptrprivate:friend class screenptr; / 定义一个友元类 screenptrscreen *sp; / 定义一个指向 screen 的指针变量 spsize_t use; / 定义一个 size_t 的整形变量 usescrptr(screen *p):sp(p),use(1) / 构造函数 use 初始化为 1 ,指针变量指始化为 pscrptr()delete sp; / 析构函数删除指针变量 sp; 定义一个 screenptr 类将对 scrptr 类其指针进行使用计数,在 screenptr 最好一个对象消失后,自动删除基础对象 class screenptrpublic:screenptr(screen *p):ptr(new scrptr(p) screenptr(const screenptr &orig):ptr(orig.ptr)(+ptr)-use;screenptr& operator=(const screenptr&);screenptr()if (-ptr)=0) delete ptr; / 当 ptr 计数为 0 时,清空 ptr 指针 private:scrptr* ptr;使用此 screenptr 建立对象 screenptr ps(new screen(10,10); 2. 让类 screenptr 支持 - 和 * 指针操作 在 screenptr 的 public: 修改为如下重载代码 class screenptrpublic:screen& operator*()return *ptr-sp;screen& operator-()return ptr-sp;const screen operator*()const return *ptr-sp;const screen operator-()const return ptr-sp;private:scrptr* ptr; * 3 .8 重载调用操作符 () / 也称函数对象 定义了调用操作符 () 的类,其对象常称为函数对象,它比函数更加灵活和方便 函数对象常用于通用算法的实参 可以为类的对象重载调用操作符 () ,如用结构实现的求绝对值的结构 struct abs_intint operator()(int val)return val=bound; private:std:string szice_type bound; 当我们在使用此类时,就可以非常方便的使用 GT_cls(5);GT_cls(6);GT_cls(7); * 3 .9 重载转换操作符 operator (type)引言 我们在操作 int,double 混合数据时 ,C+ 可以默认转换数据类型也可以强制进行类型转换 重载转换操作符就是为了方便对类产生的对象进行转换操作,它必须是成员函数实现 类的类型转换只能应用于一个转换,不能连续进行转换操作 语法格式 operator type() const return type;如 operator int() const return val;/ 转换为 int如 operator float() const return val;/ 转换为 float *4 设计指导 4 .3.1 请尽量不重载具有内置意义的操作符 如没有重载合成赋值运算符 , 编译器为默认的进行逐个赋值 , 工作方式如同复制构造函数 建议不要重载常用的内置操作符如 &( 取地址 ),( 逗号操作符 ),&,|( 逻辑运算 ) 4 .3.2 大多数操作符对类的对象没有意义 为类设计操作符 , 首先设计类的公用接口也就是公用函数 , 再用运算符重载函数来补充类的功能 相等测试请重载 =, 重载 实现输入 , 重载 ! 逻辑非 , 实现测试为对象是否为空 如字符串的 + 重载为对象连接运算 , 而不会重载为 int 的加法运算 4 .3.3 复合赋值操作符 如类重载算术操作符 (+,-,*,/,%,+,-), 就应重载对应复合算术运算 , 如类重载位运算符 (&,|,!), 就应重载对应复合位运算符 (&=,|=) 如果重载了一组关系类型的运算符 , 就建议重载完关系运算符的其它符号 4 .3.4 成员函数和非成员函数 ( 友元函数 ) 选择方案 通常对类本身的操作 ,( 如赋值 =, 下标 , 调用 (), 成员访问符 -, 自增 +, 自减 -) 请选择成员函数 通常对两个对象进行操作 ,( 如算术操作 , 位操作符 , 关系操作 , 输入输出 ) 请选择非成员函数 , 就是用友元函数实现 . 成员 / 非成员函数重载选择指导 一元操作符就是操作符有一个对象 , 如 x+,y- 等 , 通常以类的成员函数实现重载 二元操作符就是操作符有二个对象 , 如 x+y,x-y 等 , 通常以类的友元函数实现重载 . 成员与非成员函数 ( 友元函数 ) 的选择指导 . 通常对类生成的对象进行运算 , 请选用成员函数实现 . 如赋值 =, 下标 , 调用 (), 访问符 -, 自增 +, 自减 -, 复合位运算 +=,-=) . 通常对类生成的多个对象进行运算 , 请选用非成员 ( 友元函数 ). 如类对象之间的 ( 算法运算符 , 关系运算符 , 输入输出符 ) . 当然也可以把 ( 算法运算符,关系运算符 ) 重载为类的成员函数 and 友元函数 #includeusingnamespacestd;#includestr.hvoiddisplayString(MyStringms)for(inti=0;ims.getLength();i+)coutmsi;coutendl;intmain()charstra=ABCD;MyStrings1(abcd);MyStrings2(s1);MyStrings3(stra);MyStrings4;s4=s3;s1.display();s2.display();s3.display();s4.display();cout-endl;s4=s3.padLeft(10,*);s3.display();s4.display();cout-endl;MyStrings5=s4.remove(0,3);s4.display

温馨提示

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

评论

0/150

提交评论