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标准函数库)和某些应用程序均直接构建于内核 ...
随机推荐
- gpexpand error:Do not have enough valid segments to start the array.
gpstart error: Do not have enough valid segments to start the array. 这个时候需要检查一下shared_buffers设置改小点,就 ...
- Python获取并修改hosts
#!/usr/bin/env python #-*- coding: utf-8 -*- #谷歌host修改脚本 #author 坤子<root#pythonpy.com> #date 0 ...
- c# 数据库编程(利用DataSet 和 DataAdaper对象操作数据库--跨表操作)
上篇文章我们介绍了如何利用DataSet 和 DataAdaper对象来对单张表进行操作. 本文我们将介绍如何进行跨表操作. 我们通过具体例子方式进行演示,例子涉及到三张表. 1)student表(学 ...
- 如何抓取Thread Dump小结(转)
当系统性能出现问题时,需要从各个方面来查看网络环境.主机资源.查看最经变更的代码等.如果是想从代码层面解决问题,那么最有效的方法就是查看相关dump文件.如果是使用IBM JDK(我默认你是在aix环 ...
- eclipse 找不到application选项
处理如下:Window-Preferences-Run/Debug-Perspectives 中的 And Build修改为如下
- Apache ab 使用说明
第一章 简介 ab是Apache超文本传输协议(HTTP)的性能测试工具.其设计意图是描绘当前所安装的Apache的执行性能,主要是显示你安装的Apache每秒可以处理多少个请求. 第二章 说明 ab ...
- 基于visual Studio2013解决算法导论之052深度优先
题目 深度优先 解决代码及点评 // 深度优先.cpp : 定义控制台应用程序的入口点. // // 图的邻接表表示.cpp : 定义控制台应用程序的入口点. // #include < ...
- android大牛高焕堂最新力作-android架构师之路
android大牛高焕堂 个人介绍: Android专家顾问,台湾Android论坛主席,现任亚太地区Android技术大会主席,台湾Android领域框架开发联盟总架构师.发表100多篇Androi ...
- Jetty:配置概览-须要配置什么
上一节讲述了怎么配置Jetty,这节将告诉你使用Jetty你须要配置些什么. 配置Server Server实例是Jetty服务端的中心协调对象,它为全部其它Jetty服务端组件提供服务和生命周期管理 ...
- java --对象流与对象的序列化
对象流 ObjectInputStream ObjectOutputStream类分别是InputStream和OutputStream的子类,对象输出流使用writeObject(Object ob ...