面向对象技术与工具第09章.ppt_第1页
面向对象技术与工具第09章.ppt_第2页
面向对象技术与工具第09章.ppt_第3页
面向对象技术与工具第09章.ppt_第4页
面向对象技术与工具第09章.ppt_第5页
已阅读5页,还剩68页未读 继续免费阅读

下载本文档

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

文档简介

面向对象程序设计语言C+,电子科技大学计算机学院,1,第五章 运算符重载,当在使用一种程序设计语言编写程序时,我们不仅要设计新的数据类型,同时还要为新类型设计运算。一般地,用户定义类型的运算都是用函数的方式实现的。 而在一般情况下,一种类型的运算都是用运算符表达的,这很直观,语义也简单。 但是如果直接将运算符作用在用户定义类型之上,那么编译器将不能识别运算符的语义。因此,在这种情况下,我们需要一种特别的机制来重新定义作用在用户定义类型上的普通运算符的含义。这就是运算符重载的简单概念。,2,第五章 运算符重载,其实在C编译器里早就存在简单的运算符重载的概念了。考虑整型和浮点型两种加法运算: int a = 1, b; b = a + 2; float c = 1.0, d; d = c + 2.0; 在上面的两条加法语句中,都用到了运算符“+”。这符合我们数学常识。但对于C编译器来说,这两个加法却被翻译成不同的指令。这就是说,“+”运算符至少具有两种不同的解释(实现代码)。此时我们说, “+”运算符被重载了。遗憾的是,C仅支持很少量的运算符重载。,3,第五章运算符重载,C+扩充了C运算符重载的功能,允许已存在的预定义运算符在不同的上下文中做出不同的解释。 当两个字符串类进行连接的时候,我们可能用到这样的方式: class String public: String string_cat(String); ; String str1, str2, str3; str3 = str1.string_cat(str2);,4,第五章运算符重载,显然,这不如 str3 = str1 + str2 简单明了。 但问题是,C+编译器只知道+运算符是作用在整型和浮点型数据之上的,它不知道在上述表达式中+运算符的确切含义。 因此,在设计类String时,我们必须增加“+”运算符的含义。这样一来,语义变得更加清晰和易懂。,5,第五章 引论,在原来预定义的运算符含义的基础上,再增加对于某个用户定义类型的对象进行操作的新的含义。这就是运算符重载。 运算符重载后,其优先级和结合性不变。,6,第五章 引论,考虑复数的加法运算: class Complex double re, im; public: Complex(double r, double im) re=r; im=i; Complex() re = 0.0; im = 0.0; Complex add_Complex(Complex c) Complex temp; temp.re = re + c.re; temp.im = im + c.im; return temp; ;,7,/整个函数体也可简化为 return Complex(re+c.re, im+c.im);,第五章 引论,void main( ) Complex obj1(1,2),obj2(3,4); Complex obj3=obj1.add_Complex(obj2); 能不能将2个复数相加表示为:obj1+obj2 呢?,9,第五章 引论,5.1 重载运算符 C+提供了一种将标准定义的运算符用在用户自定义类型上的方法,称为运算符重载。 C+约定,如果一个成员函数的函数名字是特殊的,即由关键字operator加上一个运算符构成,如operator+。 obj1.operator+(obj2) 称为函数operator+()的显示调用形式; obj1+obj2称为函数operator+()的隐式调用形式; 函数operator+()称为运算符重载函数。,10,第五章 引论,考虑复数的加法运算: class Complex double re, im; public: Complex(double r, double im) re=r; im=i; Complex() re = 0.0; im = 0.0; Complex operator+ (Complex c) Complex temp; temp.re = re + c.re; temp.im = im + c.im; return temp; ;,11,第五章 引论,5.1 重载运算符 void main( ) Complex obj1(1,2),obj2(3,4); Complex obj3=obj1.+obj2; obj1+obj2 等价于: obj1.operator+(obj2),12,第五章 引论,5.1.1运算符重载的语法形式 在C+中,运算符通过一个运算符重载函数进行重载。运算符重载可以采用成员函数和友元函数两种重载方式,语法形式如下: (1)运算符重载函数为成员函数的语法形式为: type Class_Name:operator(参数表) /相对于Class_Name类而定义的操作 其中,type是返回类型,“”是要重载的运算符符号,Class_Name是重载该运算符的类的类名,函数名operator。,13,第五章 引论,5.1.1运算符重载的语法形式 (2)运算符重载函数为友元函数的语法形式为: type operator(参数表) /相对于该类而定义的操作 ,14,第五章 引论,5.1.2 重载运算符规则 (1) 只有少数的C+语言的运算符不能重载: : # ?: . .*,15,第五章 引论,5.1.2 重载运算符规则 (2)只能对已有的C+运算符进行重载。 (3)重载运算符时,不能改变它们的优先级,不能改变它们的结合性,也不能改变这些运算符所需操作数的数目。 (4)重载运算符的函数不能有默认的参数,否则就改变了运算符所需要的操作数的数目。,16,第五章 引论,5.1.2 重载运算符规则 (5)重载的运算符必须和用户自定义类型的对象一起使用,其参数至少应用一个是类对象(或类对象的引用)。 (6)用于类对象的运算符一般必须重载,有两个运算符:赋值运算符=和地址运算符&可以不必重载,17,第五章 引论,5.1.2 重载运算符规则 (7)重载运算符时,可以让运算符执行任意的操作, 比如将运算符重载为运算 但这样违背了运算符重载的初衷,降低程序可读性,使人无法理解程序功能。 因此,应当使重载运算符的功能类似于该运算符作用于标准类型数据时所实现的功能。 如果不能建立运算符的这种习惯用法,应该采用函数调用方法,以免造成阅读困难(除非程序员故意如此)。,18,第五章 引论,5.1 重载运算符 5.1.3 一元和二元运算符 1.一元运算符 一元运算符,不论是前缀还是后缀,都需要一个操作数。 暂时不区分前缀和后缀的重载,(5.1.5节:前缀和后缀重载的区别)。,19,第五章 引论,5.1.3 一元和二元运算符 对任意一元运算符,有: (1)成员函数重载运算符 type Class_Name:operator( ) 设obj为Class_Name的类对象,则: 显式调用方式: obj.operator() 隐式调用方式: obj 或者 obj,20,第五章 引论,5.1.3一元和二元运算符 (2)友元函数重载运算符 type operator(Class_Name Cobj) 显式调用方式: operator(obj) 隐式调用方式: obj 或者 obj (例5-5/6),21,第五章 引论,5.1.3一元和二元运算符 2.二元运算符 (1)成员函数重载运算符 type Class_Name:operator(Class_Name Cobj) 显式调用方式: obj1.operator(obj2) 隐式调用方式: obj1 obj2,22,第五章 引论,5.1.3一元和二元运算符 (2)友元函数重载运算符 type operator ( Class_Name Cobj1,Class_Name Cobj2) 显式调用方式: operator (obj1,obj2) 隐式调用方式: obj1 obj2 (例5-7/8),23,第五章 引论,5.1.3一元和二元运算符 3运算符重载为成员函数和友元函数的选择建议,24,第五章 引论,5.1 重载运算符 5.1.4 重载+和-的前缀和后缀方式 以+为例: 对于前缀方式+obj: 成员函数重载 Class_Name Class_Nam:operator+( ); 友元函数重载 Class_Nam operator+(Class_Nam ,25,第五章 引论,5.1 重载运算符 5.1.4 重载+和-的前缀和后缀方式 对于后缀方式obj+: 成员函数重载 Class_Nam Class_Nam:operator+(int); 友元函数重载 Class_Nam operator+(Class_Nam 这时,第二个参数(int)只是一个占位符号,用来区分该重载函数是前缀方式还是后缀方式,在函数内部不需要也不能使用。通常用0表示。(例5-11/12),26,第五章 引论,5.1 重载运算符 5.1.5 重载赋值运算符 赋值运算符“=”可以被重载,用户可以定义自己需要的重载“=”的运算符重载函数。重载了的运算符函数operator=不能被继承,而且它必须被重载为成员函数,一般重载格式为: X X:operator=(const X & from) /复制X的成员 拷贝构造函数和赋值运算符都是把一个对象的数据成员拷贝到另一对象。它们的区别是,拷贝构造函数要创建一个新对象,而赋值运算符则是改变一个已存在的对象的值。(例5-13),27,第五章 引论,5.1.6重载运算符( )和 运算符“()”和运算符“”不能用友元函数重载,只能采用成员函数重载。 1重载函数调用运算符( ) 对应的运算符重载函数为operator()() 设obj为类Class_Nam的一个对象,则表达式 obj(arg1,arg2) 可被解释为 obj.operator()(arg1,arg2) (例5-14),28,第五章 引论,5.1.6重载运算符( )和 2重载下标运算符 相应的运算符重载函数为operator () 设xobj为类X的对象,则表达式 xobjarg 解释为 xobj.operator (arg) (例5-15) 需要注意,这里的参数arg必须是一个整型表达式。,29,考虑一个整数数组 数组的大小在定义时初始化; 可以将对象(名)直接作为数组(名); 使用而且其大小在运行时可以改变。,class Arrayint * p;int size; public: Array(int num) size=(num6)?num:6; p=new intsize; Array( ) delete p; ,int ,void expend(int off) int * pi; pi=new int size+off; for (int n=0;nsize;n+) pin=pn; delete p; p=pi; size+=off; ,void contract(int offset) size=size-offset; ; /类结束,void main( ) int num=0; Array a_Array(10); for (;num 10; num +) a_Arraynum= num; a_Array10=10; for (n=0; n=10; n+) couta_Arrayn; ,第五章 引论,5.1.7重载输入和输出运算符 在标准文件iostream.h中,有2个标准的类类型:istream和ostream(流库的介绍参考第八章)。 对于预定义类型,用户可以方便地使用运算符“”和“”进行输入和输出。,36,输出运算符“ void main( ) int num=10; ostream 则输出10,输入运算符“”的第一个操作数是cin,它实际上是标准类类型istream的对象的引用(它的定义在文件iostream中)。 若在程序中,用户自己定义 一个istream的对象的引用,也可以直接使用运算符“”。,第五章 引论,5.1.7重载输入和输出运算符 对于类类型,用户可以重载运算符“”和“也有类似的情况,但要注意第二个参数必须是对象的引用 。(例5-16),39,class Complex double re,im; public: friend ostream ,void main( ) Complex obj1,obj2; coutobj1obj2; coutobj1“ ”obj2; ,第五章 引论,5.2 new和delete 5.2.1 为一个对象动态分配存储区 可以为任何类型(除void类型外)的数据动态分配存储空间; 当为对象动态分配存储区时,实际上是通过调用构造函数实现的; 当释放动态存储区时,是通过调用析构函数来实现的。动态存储区的分配和释放一定要成对出现。(例5-17),42,第五章 引论,5.2 new和delete 5.2.2 为一个数组动态分配存储区 void main() Complex *cp; int size; cinsize; cp=new Complexsize; ,43,第五章 引论,5.2.3 指针悬挂问题 指针悬挂就是指:使用new申请的存储空间无法访问,也无法释放。 造成指针悬挂原因是对指向new申请的存储空间的指针变量进行赋值修改。 char * p,* q; p=new char10; q=new char10; strcpy(p, “abcd“); q=p; delete p; delete q; /错误,同样的空间被释放两次,44,对象的拷贝有两种方式:初始化和赋值。 将一个对象的数据成员对应地赋值给另一个对象的数据成员; 如果一个类包含有指针类型的数据成员,那么,该类的对象的拷贝(初始化和赋值)就可能会有问题。 对象的指针成员直接赋值,就可能导致指针悬挂。 需要重新定义拷贝构造函数和超载“=”的函数,class String char * pstr;int sz; public: String (int s) pstr=new char sz=s; String ( ) delete pstr; ;,void main( ) String str1(10); String str2=str1; String str3(10); str3=str1; 执行该程序,会出现问题。Why?,缺省的拷贝构造函数为: String: String(const String ,缺省的超载”=”函数为: String String :operator=(const String ,集合的实现,C+中没有集合类型,可以定义一个集合类来实现。 与集合相关的操作有: 加入一个元素到集合中 判断一个元素是否在集合中 可以取两个集合的交集和并集 删除集合中的一个元素 可以扩充集合 可以输入、输出集合的所有元素 集合可以互相复制 可以清空一个集合,等,class Set int * p; int size; int have; public: Set(int a); Set( );,void expend(int offset); void add(int ); int In(int ); void delete_item(int); Set operator +(Set ); Set operator *(Set t);,friend void operator(ostream ,Set Set:operator*(Set t) Set temp(size); for (int a=0;a-1) temp.add(pa); return temp;,Set Set:operator+( Set t) Set temp(size+t.size); int a; for (a=0;ahave;a+) temp.add(pa); for (a=0;at.have;a+) if (In(t.pa)=-1) temp.add(t.pa); return temp; ,Set:Set (const Set ,Set Set:operator=(const Set ,第五章 引论,5.3 类型转换运算符的重载 类型转换是将一种类型的值转换为另一种类型的值。 对于类类型,是否也存在一种类型转换机制,使得类对象之间能进行类型转换? 一般,类对象的类型转换可由构造函数和转换函数实现。 这种转换常称为用户定义的类型转换或类类型转换。在C+中,类被视为用户定义的类型,可以像系统预定义类型一样进行类型转换。,58,第五章 引论,5.3 类型转换运算符的重载 C+语言允许的类型转换有4种: 标准类型-标准类型 标准类型-类类型 类类型-标准类型 类类型-类类型,59,第五章 引论,5.3 类型转换运算符的重载 5.3.1 标准类型转换为类类型 可以通过自定义的重载赋值号“=”的函数和构造函数实现标准类型-类类型;它们都需要有标准类型的参数。 具有标准类型参数的构造函数说明了一种从参数类型到该类类型的转换。(例5-24/25),60,class INTEGER int num; public: INTEGER (int i); INTEGER (const char * str); ; INTEGER:INTEGER(int i) num=i; INTEGER:INTEGER(const char *str) num=strlen(str); void main() INTEGER obj1= 1; INTEGER obj2=“Cheng“; obj1=20; /obj1.operator=(INTEGER(20); obj2=“Du“ ; /* obj2.mem_fun(INTEGER(3);*/ ,第五章 引论,5.3 类型转换运算符的重载 5.3.2 类类型转换函数 带一个参数的构造函数可以进行类型转换,但是它的转换功能很受限制。 引入一种特殊的成员函数:类型转换函数,它在类对象之间提供一种类似显式类型转换的机制。,62,第五章 引论,5.3 类型转换运算符的重载 5.3.2 类类型转换函数 C+允许程序员为类定义一个类型转换函数,它的语法是 Class_Name:operator type( ) return (type类型的实例); 类型转换函数没有参数,没有返回类型,但这个函数体内必须有一条返回语句,返回一个type类型的实例。,63,第五章 引论,5.3 类型转换运算符的重载 5.3.2 类类型转换函数 class INTEGER int num; public: INTEGER(

温馨提示

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

评论

0/150

提交评论