运算符重载 (2)幻灯片.ppt
《运算符重载 (2)幻灯片.ppt》由会员分享,可在线阅读,更多相关《运算符重载 (2)幻灯片.ppt(76页珍藏版)》请在淘文阁 - 分享文档赚钱的网站上搜索。
1、运算符重载第1页,共76页,编辑于2022年,星期三 本章要点:什么是运算符重载什么是运算符重载 一元运算符的重载一元运算符的重载 二元运算符的重载二元运算符的重载 通过友元函数实现重载通过友元函数实现重载 输出、输入运算符的重载输出、输入运算符的重载第2页,共76页,编辑于2022年,星期三在前面学习类和对象的时候,我们明确了这样一个概念:定义一个类就是定义一种新类型。因此,对象和变量一样,可以作为函数的参数传递,可以作为函数的返回值的类型,也可以说明对象数组,甚至还可能有类类型的常量。在基本数据类型上,系统提供了许多预定义的运算符,它们以一种简洁的方式工作。例如“+”运算符:intx,y;
2、y=x+y;表示两个整数相加,很简洁。但是,两个字符串合并:char x20,y10;/定义两个字符串类型/strcat(x,y);表达起来就不如“y=x+y;”那样直观简洁。因此,为了表达上的方便,希望已预定义的运算符,也可以在特定类的对象上以新的含义进行解释。如在string类对象x、y的环境下,运算符“+”能被解释为字符串x和y的合并。换言之,希望预定义运算符能被重载,让用户自定义的类也可以使用。一、为什么要进行运算符重载第3页,共76页,编辑于2022年,星期三C语言中有多种内置的数据类型,例如int、float、double和char等等。对应于每一种类型都有一系列的内置运算符,比如
3、加法运算符“+”和乘法运算符“*”。就拿运算符“+”来说吧,它可以用于int值,也可以用于float,虽然使用相同的运算符,但生成的代码不同,因为整数和浮点数在内存中的表示是不同的。这时,“+”运算符具有两种不同的解释(即实现代码)。也就是说,像“+”这样的运算符在C语言中已被重载。但是,C语言仅支持少量有限的运算符重载。C+语言对重载功能进行了扩充,也允许我们在自己定义的类上添加运算符,允许对已存在的预定义运算符由我们在不同的上下文中做出不同的解释。比如,经过运算符重载,我们可以直接对两个字符串string类对象进行加法运算string x,y;x=x+y;可以直接输出复数类CComplex
4、对象Ccomplex c;cout c;第4页,共76页,编辑于2022年,星期三通过运算符重载,程序代码就显得简洁明了,类对象的使用也方便了。这就是我们重载运算符的目的。第一个基本动作就这么简单,没问题吧?好了,如果第一关没问题,可以继续前进了。先看看下面这段话:因为本书针对C+的入门读者,所以对一些深层次复杂的运算符重载,比如new和delete的重载以及类型转换等等不做介绍,以免倒了你的胃口。这里我们只介绍一下常用的运算符重载的实现,让大家明白运算符重载是怎么回事、如何实现,就算是完成任务了。如果想进一步学习复杂的高级的重载,可以参见别的参考书。运算符重载函数可以作为类的成员函数,也可以
5、作为类的友元函数来实现。下面对这两种不同的实现分别讲述。第5页,共76页,编辑于2022年,星期三通俗地说,重载运算符就是在写函数,用这个运算符函数体对重载的运算符的含义做出新的解释。这里所解释的含义与重载该运算符的类有关,比如,字符串类重载的加运算符“+”,实际上是对两个字符串进行拼接。重载后的运算符还是按这些运算符的表达方式使用。例如,在一个string类中重载了运算符“+”为两个字符串的合并,我们可以这样写:string s1,s2;s1=s1+s2;/合并串s1和串s2,存放到新串s1中。为了把运算符从头到脚地看个明明白白,我们创建一个新类:计数器类CCounter,逐步地根据需求来完
6、善此类,并进一步地解释为什么要重载运算符以及如何来重载。例15.1 创建类CCounter,类CCounter的一个对象可以用来在循环中计数(感到惊奇吧),而且这个类的对象还可以用在其它程序中以实现数字递增、递减或跟踪一些值的地方。二、以成员函数实现运算符重载第6页,共76页,编辑于2022年,星期三程序清单 C15_01.cpp/类类Counter的简单定义及实现的简单定义及实现#include using namespace std;class CCounterpublic:CCounter():m_val(0)/缺省构造函数,成员变量缺省构造函数,成员变量m_val初始化为初始化为0CC
7、ounter()/什么事都不干的析构函数什么事都不干的析构函数/下面两个函数是私有变量下面两个函数是私有变量m_val的存取访问函数的存取访问函数unsigned GetVal()const return m_val;void SetVal(unsigned x)m_val=x;private:unsigned m_val;main()CCounter counter;cout counter的值是:的值是:counter.GetVal()endl;输出结果输出结果counter的值是:0第7页,共76页,编辑于2022年,星期三程序分析:事实上,上面创建的CCounter类是一个“垃圾类”,
8、没有任何用处,只有惟一的一个成员变量m_val,而且被缺省的构造函数初始化为零。用类CCounter创建的对象不能像整型变量那样进行自增和自减运算,也不能进行加法、赋值或者其它的算术操作。更恶劣的是,这个类创建的对象的输出也是一个问题,不能像整型数那样直接用cout进行输出。通过我们即将要学习的运算符重载来对CCounter类进行“教化”,使它能够像一般的整型数一样来进行一系列的算术运算。再次说明,我们只是想通过对类CCounter的逐步改造来讲解运算符重载的知识,至于这个类本身,用处倒不大。第8页,共76页,编辑于2022年,星期三1.重载一元运算符:递增运算符重载一元运算符:递增运算符“+
9、”(1)通过添加成员函数)通过添加成员函数Increment(),实现自增功能,实现自增功能运算符重载可以使类获得使用这些运算符的运算符重载可以使类获得使用这些运算符的“权限权限”。例如,我们。例如,我们可以通过下面两种方式让类可以通过下面两种方式让类CCounter的对象具有自增运算的功能。的对象具有自增运算的功能。一种方式是通过在类一种方式是通过在类CCounter中添加一个实现自增功能的方法中添加一个实现自增功能的方法Increment(),如下面例,如下面例15.2:例例15.2 给给CCounter类添加自增函数类添加自增函数Increment()。第9页,共76页,编辑于2022年
10、,星期三程序清单程序清单 C15_02.cpp#include using namespace std;class CCounterpublic:CCounter():m_val(0)CCounter()unsigned GetVal()const return m_val;void SetVal(unsigned x)m_val=x;void Increment()+m_val;/自增函数,将变量的值加自增函数,将变量的值加1private:unsigned m_val;main()CCounter counter;cout counter的值是:的值是:counter.GetVal()en
11、dl;counter.Increment();cout 调用自增函数之后,调用自增函数之后,;cout counter的值是:的值是:counter.GetVal()endl;输出结果输出结果counter的值是:0调用自增函数之后,counter的值是:1第10页,共76页,编辑于2022年,星期三程序分析:程序分析:例例15.2中,在类中,在类CCounter中添加了自增函数中添加了自增函数Increment(),虽然它可以正常工作,但是使用起来和运算符,虽然它可以正常工作,但是使用起来和运算符“+”比较起来可是差远了,太麻烦了。似乎听见哪比较起来可是差远了,太麻烦了。似乎听见哪有抗议声,
12、哦,原来是上面的程序在喊:有抗议声,哦,原来是上面的程序在喊:“为什么不为什么不给我添加给我添加+运算符运算符”。别急,当然可以满足它的愿。别急,当然可以满足它的愿望了,通过重载运算符望了,通过重载运算符+就可以实现。就可以实现。第11页,共76页,编辑于2022年,星期三(2)重载前缀运算符“+”1)重载前缀运算符“+”,返回类型为void要重载前缀+运算符,可以通过运算符重载函数实现,我们这里是把运算符重载函数作为类的成员函数实现的,它的语法形式如下:其中,returntype是返回值类型,operator是关键字,“op”是要重载的运算符符号,classname是重载该运算符的类的名称。
13、重载函数的函数名是由关键字operator后面加上要重载的运算符符号组成的,为operator op。这里我们用“op”泛指可被重载的运算符。因此,自增运算符+可以按如下的形式进行重载:void operator+();returntype classname:operator op(参数表参数表)/相对于该类而定义的操作代码相对于该类而定义的操作代码第12页,共76页,编辑于2022年,星期三例15.3 在CCounter类中通过运算符+的重载,实现CCounter类的自增运算+。程序清单 C15_03.cpp/重载运算符重载运算符+,运算符重载函数作为类,运算符重载函数作为类CCounte
14、r的成员函数的成员函数#include using namespace std;class CCounterpublic:CCounter():m_val(0)CCounter()unsigned GetVal()const return m_val;void SetVal(unsigned x)m_val=x;void Increment()+m_val;void operator+()+m_val;/重载运算符重载运算符+private:unsigned m_val;第13页,共76页,编辑于2022年,星期三main()CCounter counter;cout counter的值是:的
15、值是:counter.GetVal()endl;counter.Increment();cout 调用自增函数之后,调用自增函数之后,;cout counter的值是:的值是:counter.GetVal()endl;+counter;cout 使用自增运算符使用自增运算符+之后,之后,;cout counter的值是:的值是:counter.GetVal()endl;输出结果输出结果counter的值是:0调用自增函数之后,counter的值是:1使用自增运算符+之后,counter的值是:2第14页,共76页,编辑于2022年,星期三程序分析:在上面的程序中,函数:void operato
16、r+()+m_val;实现了运算符+的重载。在main()函数中,语句:+counter;对象counter,使用了类CCounter重载的运算符+,这种语法形式与我们期望类CCounter对象所具有的形式非常接近。但是,或许你想让类CCounter对象具有更多附加的功能,比如检查CCounter类对象是否超出了最大值范围等等。第15页,共76页,编辑于2022年,星期三2)重载运算符“+”,返回一个CCounter类对象,通过创建临时变量实现不知道你是否注意到,我们上面重载的自增运算符有一个很大的缺陷,那就是如果你想把CCounter类对象放在赋值运算符的右侧,那么对不起,编译器会不客气地报
17、错,你不妨试试。把CCounter类对象放在赋值运算符的右侧,例如:CCounter counter2=+counter;这条语句试图建立一个新的CCounter类对象counter2,然后把对象counter自增后的值赋给这个对象。内置的拷贝构造函数将处理赋值运算,但是现在的自增运算符并没有返回一个CCounter类对象,而是返回空类型void,我们不能把一个空类型void对象赋给一个CCounter类对象。那怎么办?下面我们就来解决这个棘手的问题。显然,我们只需要让重载运算符函数返回一个CCounter类对象问题就解决了,这样返回的对象值就可以赋给另一个CCounter类对象了。那么返回哪
18、个对象呢?一种方法是创建一个临时对象,然后返回。第16页,共76页,编辑于2022年,星期三例15.4 在CCounter类中重载运算符+,并返回一个CCounter类型的临时对象。程序清单 C15_04.cpp/重载运算符重载运算符+,并返回一个临时对象,并返回一个临时对象#include using namespace std;class CCounterpublic:CCounter():m_val(0)CCounter()unsigned GetVal()const return m_val;void SetVal(unsigned x)m_val=x;void Increment()
19、+m_val;CCounter operator+();/重载重载+运算符,返回值为运算符,返回值为CCounter类型类型private:unsigned m_val;第17页,共76页,编辑于2022年,星期三CCounter CCounter:operator+()+m_val;CCounter temp;temp.SetVal(m_val);return temp;main()CCounter counter;cout counter的值是:的值是:counter.GetVal()endl;counter.Increment();cout 调用自增函数之后,调用自增函数之后,;cout
20、 counter的值是:的值是:counter.GetVal()endl;+counter;cout 使用自增运算符使用自增运算符+之后之后,;cout counter的值是:的值是:counter.GetVal()endl;CCounter counter2=+counter;cout counter2的值是:的值是:counter2.GetVal()endl;cout counter的值是:的值是:counter.GetVal()endl;输出结果输出结果counter的值是:0调用自增函数之后,counter的值是:1使用自增运算符+之后,counter的值是:2counter2的值是:
21、3counter的值是:3 第18页,共76页,编辑于2022年,星期三程序分析:在上面这个版本的程序中,运算符重载函数operator+的返回值为一个CCounter类对象。在函数operator+中,我们创建了一个临时对象temp:CCounter temp;而且通过语句temp.SetVal(m_val);将对象temp的值设置为当前对象的值。临时对象被返回而且赋值给对象counter2。CCounter counter2=+counter;至此,上面的实现好像是很完美了,但是,有一个问题,就是:为什么我们要创建一个临时对象?”,记住:每个临时对象被创建而且使用完之后必须要被销毁这是一个
22、潜在的“奢侈”的操作,要耗费资源,况且对象counter已经存在,并且已经有正确的值,那么为什么不直接返回它呢?我们可以通过使用this指针来解决这个问题。第19页,共76页,编辑于2022年,星期三3)重载运算符“+”,通过this指针返回一个CCounter类对象的引用正如我们在第13章中讨论的那样,this指针是类的所有成员函数的隐含参数,因为运算符重载函数operator+是类的成员函数,所以this指针是该函数的隐含参数。this指针指向对象counter,如果间接引用this指针(*this)则其返回对象counter,对象counter的成员变量m_val已经有正确的值。例15.
23、5 在CCounter重载运算符函数中返回间接引用this指针的值,这样就可以避免创建一个临时对象,从而可以提高程序运行的效率。第20页,共76页,编辑于2022年,星期三程序清单程序清单 C15_05.CPP/返回返回this指针的间接引用指针的间接引用#include using namespace std;class CCounterpublic:CCounter():m_val(0)CCounter()unsigned GetVal()const return m_val;void SetVal(unsigned x)m_val=x;void Increment()+m_val;con
24、st CCounter&operator+();/重载重载+运算符,返回运算符,返回this指针的间接引用指针的间接引用private:unsigned m_val;const CCounter&CCounter:operator+()+m_val;return*this;第21页,共76页,编辑于2022年,星期三main()CCounter counter;cout counter的值是:的值是:counter.GetVal()endl;counter.Increment();cout 调用自增函数之后,调用自增函数之后,;cout counter的值是:的值是:counter.GetVa
25、l()endl;+counter;cout 使用自增运算符使用自增运算符+之后之后,;cout counter的值是:的值是:counter.GetVal()endl;CCounter counter2=+counter;cout counter2的值是:的值是:counter2.GetVal()endl;cout counter的值是:的值是:counter.GetVal()endl;输出结果输出结果counter的值是:0调用自增函数之后,counter的值是:1使用自增运算符+之后,counter的值是:2counter2的值是:3counter的值是:3第22页,共76页,编辑于202
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 运算符重载 2幻灯片 运算 重载 幻灯片
限制150内