C++学习之路—运算符重载(一)概念、方法及规则
(根据《C++程序设计》(谭浩强)整理,整理者:华科小涛,@http://www.cnblogs.com/hust-ghtao转载请注明)
1 什么是运算符重载
先来说下什么是重载吧!所谓重载,就是赋予新的含义。重载包括函数重载和运算符重载。函数重载就是对一个已有的函数赋予新的含义,使之实现新的功能,因此,同一个函数名就可以用来代表不同功能的函数,也就是一名多用。函数重载在以后的博客中会陆续介绍,这个系列先只介绍运算符重载。
运算符也可以重载,实际上,我们已经在不知不觉中使用了运算符重载。例如,大家大家已经习惯于用加法运算符“+”对整数、单精度数和双精度数进行加法,其实,计算机处理整数、单精度数和双精度数加法的操作方法是不同的,由于C++已经对运算符“+”进行了重载,使“+”能适用于int、float、double类型的不同的运算。
现在要讨论的问题是:用户能否根据自己的需要对C++已经提供的运算符进行重载,赋予它们新的含义,使之一名多用。例如,能否用“+”号进行两个复数的相加。在C++中是不能在程序中直接用运算符“+”对复数进行相加运算。用户必须自己设法实现复数相加。
最容易想到的方法是:自己定义一个专门的函数来实现复数相加。例如:
1: class Complex //定义Complex类
2: {
3: public:
4: ...
5: Complex complex_add( Complex& c2 ) ; //声明复数相加函数
6: private:
7: double real ; //实部
8: double imag ; //虚部
9: };
10:
11: Complex Complex :: complex_add( Complex& c2 ) //定义复数相加函数
12: {
13: Complex c ;
14: c.real = real + c2.real ;
15: c.imag = imag + c2.imag ;
16: return c ;
17: }
此方法采用在Complex类中定义complex_add函数,其作用是将两个复数相加,在该函数体中定义一个Complex类对象c作为临时对象。其中的赋值语句相当于
1: c.real = this->real + c2.real ;
2: c.imag = this->imag + c2.imag ;
this是当前对象的指针。
利用上述方法得到的结果是正确的,但调用很不方便。人们自然会想到:能否也和整数的加法运算一样,直接用“+”来实现复数运算,这就需要对“+”进行重载。
2 运算符重载的方法
运算符重载的方法是定义一个重载运算符的函数,使指定的运算符不仅能实现原有的功能,而且还能实现函数中指定的新功能。在使用被重载的运算符时,系统就自动调用该函数,以实现相应的功能。运算符的重载实质上是函数的重载。
运算符重载的一般格式如下:
函数类型 operator 运算符名称(形参表)
{ 对运算符的重载处理 }
在上面的一般格式中,operator是关键字,是专门用于定义重载运算符的函数的,函数名使用operator和运算符组成。
例,对运算符“+”进行重载,使之能用于两个复数相加:
1: class Complex
2: {
3: public:
4: ...
5: Complex operator + ( Complex& c2 ) ; //声明重载运算符 + 的函数
6: private:
7: double real ;
8: double imag ;
9: };
10:
11: Complex Complex :: operator + ( Complex& c2 ) //定义重载运算符 + 的函数
12: {
13: Complex c ;
14: c.real = real + c2.real ;
15: c.imag = imag + c2.imag ;
16: return c ;
17: }
经过这样的声明和定义之后,若c1、c2、c3都是Complex类的对象,在进行两个复数相加时,就可以这样:
1: c3 = c1 + c2 ;
将运算符"+"'重载为类的成员函数后,C++编译系统将程序中的表达式"c3=c2+c1"解释为" c1.operator + ( c2 ) ",表示以c2为实参调用c1的运算符重载函数operator+,进行两个复数相加。
通过以上的比较可以看到,无论是通过自定义complex_add函数,还是重载“+”运算符,两个程序的结构和执行过程基本上是相同的,作用相同,运行结果也相同。那为什么还要进行运算符重载呢?这就要从用户的角度来思考问题,虽然重载运算符所实现的功能完全可以由函数实现,但是使用运算符重载能使用户易于编写、阅读和维护。
注意:运算符被重载后,其原有的功能仍然保留,没有丧失或改变。也就是说同一个运算符可以代表不同的功能,当编译系统需要判别该执行哪一个功能的时候,是根据表达式的上下文决定的,即根据运算符两侧的数据类型来决定的。
总结一下:本来C++提供的运算符只能用于标准类型数据的运算,但C++程序设计的重要基础是类和对象,如果C++的运算符无法用于类和对象,则类和对象的应用将会受到很大的限制。为了解决这个问题,使类和对象有更强的生命力,C++允许重载现用的运算符,使这些简单易用、众所周知的运算符能直接应用于自己定义的类和对象。
3 重载运算符的规则
(1)C++不允许用户自己定义新的运算符,只能对已有的C++运算符进行重载。
(2)C++允许重载的运算符。
记住不能重载的运算符:
成员访问运算符: .
成员指针运算符:*
作用域运算符: ::
长度运算符:sizeof
条件运算符:?:
(3)重载不能改变运算符运算对象的个数。
如关系运算符“<”“>”等是双目运算符,重载后仍为双目运算符,需要两个参数。有些运算符既可以作为单目运算符,也可以作为双目运算符,这就需要分别重载。
(4)重载不能改变运算符的优先级别。
(5)重载不能改变运算符的结合性。
(6)重载运算符的函数不能有默认的参数。否则就改变了运算符参数的个数,与(3)矛盾。
(7)重载的运算符必须和用户定义的自定义类型的对象一起使用,其参数至少应有一个是类的对象或类的引用。也就说参数不能全是C++的标准类型,以防止用户修改用于标准类型数据的运算符的性质。
(8)用于类对象的运算符一般必须重载,但有两个例外,运算符“=”和“&”不必用户重载。
(9)应当使重载运算符的功能类似于该运算符作用于标准类型数据时所实现的功能。
C++学习之路—运算符重载(一)概念、方法及规则的更多相关文章
- C++学习之路—运算符重载(二)运算符重载作为类的成员函数和友元函数
(根据<C++程序设计>(谭浩强)整理,整理者:华科小涛,@http://www.cnblogs.com/hust-ghtao转载请注明) 对运算符重载的函数有两种处理方式:(1)把运算符 ...
- C++学习26 运算符重载的概念和语法
所谓重载,就是赋予新的含义.函数重载(Function Overloading)可以让一个函数名有多种功能,在不同情况下进行不同的操作.运算符重载(Operator Overloading)也是一个道 ...
- C++学习笔记之运算符重载
一.运算符重载基本知识 在前面的一篇博文 C++学习笔记之模板(1)——从函数重载到函数模板 中,介绍了函数重载的概念,定义及用法,函数重载(也被称之为函数多态)就是使用户能够定义多个名称相同但特征标 ...
- scala学习手记7 - 运算符重载
从语法上来说scala是没有运算符的.之前的一节里也曾提到过scala的运算符实际上是方法名,如1 + 2实际上就是1.+(2).我们可以将之视为运算符,是因为scala的一个特性:如果方法的参数小于 ...
- 【dart学习】之运算符重载
一,什么是运算符重载(operator overloading) 在软件开发过程中,运算符重载(英语:operator overloading)是多态的一种.运算符重载通常只是一种语法糖,这种语法对语 ...
- Python3学习之路~8.1 socket概念及参数介绍
一 socket介绍 TCP/IP 基于TCP/IP协议栈的网络编程是最基本的网络编程方式,主要是使用各种编程语言,利用操作系统提供的套接字网络编程接口,直接开发各种网络应用程序. socket概念 ...
- osgi实战学习之路:3. osgi分层概念及相互合作demo
源码下载 分层: modual: 主要作用于包级管理与共享代码 lifecycle: 主要作用于执行期间的模块管理与訪问osgi底层框架 service: 主要作用于多模块之间的相互通信 demo: ...
- vb编程学习之路之基础与概念总结
OOP (Object Oriented Programming)面向对象程序设计/面向对象编程 对象是代码和数据的集合,对象的三要素:属性.事件.方法 对象的命令规则:必须以字母或汉字开头,不能以数 ...
- Linux学习之路三:重要概念之Linux系统层次结构
上图来自Unix编程圣经<APUE>英文第二版.如图,处于最中心的是系统内核,负责机器硬件资源管理,进程管理等:shell,函数库(值得记住的是C标准函数库)和某些应用程序均直接构建于内核 ...
随机推荐
- Ubantu指令收藏
Ubuntu常用命令大全,学习ubuntn系统的朋友可以收藏下,用ctrl+F查找即可 一.文件/文件夹管理 ls 列出当前目录文件(不包括隐含文件) ls -a 列出当前目录文件(包括隐含文件) ...
- jQuery prop 全选和全不全
$('#ckAll').click(function() { var value = $(this).is(':checked') ? true : false; $("input[name ...
- python3.4.3将汉字转换为大写拼音首字母
from pypinyin import pinyin a=pinyin(u'杨强',type=FIRST_LETTER) --->此时返回一个列表并赋给a(元素也是列表) b=[] - ...
- 临时节点不能有child 子节点
[zk: 127.0.0.1:2181(CONNECTED) 67] create '/zk01/0001/aaaa' dada Ephemerals cannot have children: /z ...
- java中排序一个字符串数组
package test_set_map; import java.util.Arrays; import java.util.Collections; public class Test_Colle ...
- uC/OS II 函数说明 之–OSTaskCreate()与OSTaskCreateExt()
1. OSTaskCreate() OSTaskCreate()建立一个新任务,能够在多任务环境启动之前,或者执行任务中建立任务.注意,ISR中禁止建立任务,一个任务必须为无限循环结构. ...
- ListView优化问题
可以参考:http://blog.csdn.net/bill_ming/article/details/8817172和http://blog.csdn.net/xiangjai/article/de ...
- 三、nginx301跳转302跳转
301跳转设置: server { listen 80; server_name downcc.com; rewrite ^/(.*) http://www.downcc.com/$1 permane ...
- Ubuntu一些配置和技巧
安装google-chrome wget https://dl.google.com/linux/direct/google-chrome-stable_current_i386.deb sudo d ...
- 令牌桶在数据通信QoS流量监管中的应用
令牌桶(Tocken Bucket,以下简称TB)在流量监管(以下简称CAR)功能中完成对流量进行限速的作用.流量监管主要是应用与网络边缘,从而保证核心设备的正常数据处理. 在流量监管的处理过程中,首 ...