C++中的运算符重载
首先思考以下几个问题:
1.什么是运算符重载?
2.为什么要重载运算符,它有什么用?
3.可以重载哪些运算符?
4.重载运算符有哪些规则?
一、基本概念
我们在程序中使用各种操作符,比如加(+)、赋值(=)等等。运算符重载可以重新赋予操作符的含义,举个栗子,对于加号操作符,一般都是将两个数进行相加,而不能将两个自定义类的对象相加,但是通过运算符重载可以这么做。
重载运算符是具有特殊名称的函数,函数具有哪些特征呢?1.函数名称;2.返回类型;3.参数列表;4.函数体。
1.名称的写法是保留字operator后接需定义的操作符号;
2.返回类型后面再说;
3.参数:参数数目与该运算符作用的运算对象数目相同,但如果是作为一个类的成员函数,(显式)参数数目比运算对象总数少一个(因为有一个隐含的this形参)。
1.哪些运算符可以被重载
只知道哪些可以、哪些不可以被重载,没有太大意义。
2.重载运算符怎么调用
如果是非成员运算符函数:
star1 + star2; //普通表达式
operator+(star1, star2); //等价的函数调用
如果是成员运算符函数:
star1 += star2; //基于调用的表达式
star1.operator+=(star2); //等价的调用
二、为什么要重载运算符
大多数人平时很少用到运算符重载,因为运算符重载的功能一般都可以通过直接写一个普通函数实现。但运算符重载可以使的程序更加“优美”,在有的情形下,可以使我们更容易使用标准库容器和算法。
三、输入、输出运算符

我们现在有一个类SuperStar,代表超级巨星,它有一个成员变量代表巨星的姓名。
现在我们的任务是输入、输出巨星的名字。
class SuperStar
{
public:
SuperStar();
~SuperStar();
private:
string m_strName; //姓名
};
1.输出运算符<<
输出运算符第一个参数是ostream的引用,第二个参数是一个常量的引用。
ostream &operator<<(ostream &os, const SuperStar &star)
{
os << star.m_strName;
return os;
}
2.输入运算符>>
输入运算符第一个参数是将要读取的流的引用,第二个参数是将要读入到的对象的引用。
istream &operator>>(istream &is, SuperStar &star)
{
if (is)//检查是否输入成功
is >> star.m_strName;
else
star = SuperStar();
return is;
}
值得注意的是参数为什么是引用,还有参数为什么是/不是常量。
输入输出运算符必须是非成员函数,但是IO运算符需要读写类的非公有成员,所以一般被声明为友元。
friend istream& operator>>(istream &, SuperStar &);
friend ostream& operator<<(ostream &, const SuperStar &);
四、算术和关系运算符
1.相等运算符==
假如现在有2个明星,一个叫饭冰冰,另一个叫凤咀
VS 
我们根据名字来判断她们是不是一样的(这样做也许有失合理,请不要太在意细节)
bool operator==(const SuperStar &star1, const SuperStar &star2)
{
return star1.m_strName == star2.m_strName;
} bool operator!=(const SuperStar &star1, const SuperStar &star2)
{
return !(star1 == star2);
}
让我们试一下效果:
SuperStar star1;
SuperStar star2;
cout << "亲爱的经纪人,请创造1号女星:";
cin >> star1;
cout << "请创造2号女星:";
cin >> star2;
cout << "1号" << star1 << ";2号" << star2 << endl;;
cout << "她们" << ((star1 == star2) ? "相同" : "不相同") << endl;

2.算术运算符+
SuperStar operator+(const SuperStar &star1, const SuperStar &star2)
{
SuperStar star3 = star1;
star3 += star2;
return star3;
}
上面使用了复合赋值运算符+=,这一点后面会将。(note:如果类同时定义了算术运算符和复合赋值运算符,通常应使用复合赋值运算符来实现算术运算符)
五、赋值运算符
1.赋值运算符=
凤咀对自己名字不满意,于是想改名叫饭冰冰。
:“我叫饭冰冰,你爱我吗?”
SuperStar & SuperStar::operator=(const SuperStar &star)
{
if (this != &star)
{
m_strName = star.m_strName;
}
return *this;
}
这里要注意赋值给自己的情况,有一本叫《C++沉思录》的书里面有深入的讲解。
赋值运算符必须定义为成员函数。
2.复合赋值运算符+=
凤咀想:直接叫别人的名字不太好,把她名字加在我后面吧!
:“我叫凤咀饭冰冰,你还爱我吗?”
SuperStar & SuperStar::operator+=(const SuperStar &star)
{
m_strName += star.m_strName;
return *this;
}
复合赋值运算符不非得是类的成员,不过倾向于把所有赋值运算都定义在类内部。
六、递增和递减运算符
1.前置递增/递减运算符
首先在类中定义它们:
SuperStar &operator++();
SuperStar &operator--();
具体实现:
SuperStar & SuperStar::operator++()
{
check();
++curr;
return *this;
}
SuperStar & SuperStar::operator--()
{
--curr;
check();
return *this;
}
注意其中检查是否越界,如果越界,将会抛出out_of_range异常。
2.后置递增/递减运算符
为了区分前置与后置,后置版本接受一个额外的(不使用的)int类型的参数。
SuperStar & SuperStar::operator++(int)
{
SuperStar ret = *this;
++*this;
return ret;
}
SuperStar & SuperStar::operator--(int)
{
SuperStar ret = *this;
--*this;
return ret;
}
后置运算符调用各自的前置版本来完成实际的工作。
以上只是运算符重载的一小部分,想认识更多还需要多看书多思考。
C++中的运算符重载的更多相关文章
- C++中的运算符重载注意事项
1.C++中的运算符重载的方式有三种: a.类成员函数重载 b.友元函数重载 c.普通函数重载 注意: a.我们主要使用的方式主要是用:类成员函数和友元函数来实现运算符的重载. b.其实用普通函数理论 ...
- c++中的运算符重载operator2(翁恺c++公开课[31-33]学习笔记)
上一篇operator1中,大概说了下重载的基本用法,接下来对c++中常见的可重载运算符归一下类,说一下它们的返回值,讨论下较为复杂的运算符重载上的坑
- c++中的运算符重载operator1(翁恺c++公开课[30]学习笔记)
运算符重载规则: 只有已经存在的运算符才能被重载,不能自己制造一个c++中没有的运算符进行重载 重载可以在类或枚举类型内进行,也可以是全局函数,但int.float这种已有的类型内是不被允许的 不能二 ...
- C++走向远洋——50(Time类中的运算符重载、一目,二目比较运算符、二目赋值运算符、二目加减法运算符)
*/ * Copyright (c) 2016,烟台大学计算机与控制工程学院 * All rights reserved. * 文件名:text.cpp * 作者:常轩 * 微信公众号:Worldhe ...
- C++走向远洋——49(项目一2、复数类中的运算符重载、类的友元函数)
*/ * Copyright (c) 2016,烟台大学计算机与控制工程学院 * All rights reserved. * 文件名:text.cpp * 作者:常轩 * 微信公众号:Worldhe ...
- C++走向远洋——48(项目一1、复数类中的运算符重载、类的成员函数)
*/ * Copyright (c) 2016,烟台大学计算机与控制工程学院 * All rights reserved. * 文件名:text.cpp * 作者:常轩 * 微信公众号:Worldhe ...
- C++中的运算符重载练习题
1.RMB类 要求: 定义一个RMB类 Money,包含元.角.分三个数据成员,友元函数重载运算符‘+’(加) 和 ‘-’(减),实现货币的加减运算 例如: 请输入元.角 分: ...
- 在Lua中进行运算符重载
在C++里面运算符是可以重载的,这一点也是C++比较方便的一个地方.在Lua中其实也是可以模拟出运算符的重载的. 在Lua中table中元素的运算都是和一个叫做元表有关的,在一个table型的变量上都 ...
- Python 中的运算符重载
本文的文字及图片来源于网络,仅供学习.交流使用,不具有任何商业用途,如有问题请及时联系我们以作处理 一种运算符对于不同类型的对象,有不同的使用方式.例如, + 用于整型对象,表示两个数相加:用于字符串 ...
随机推荐
- 初学Node(二)package.json文件
package.json简介 package.json在Node项目中用于描述项目的一些基本信息,以及依赖的配置,一般每一个Node项目的根目录下都有一个package.json文件. 在项目的根目录 ...
- 使用HyperV虚拟机装系统
新建虚拟机 新建虚拟机 进行相关参数设置 选择系统安装镜像位置,名称及位置 指定代数一般为1代即可 为虚拟机运行分配内存 创建虚拟硬盘或连接已有虚拟硬盘,并分配硬盘空间 核对创建虚拟机相关信息 安装系 ...
- Ajax的实现
一.JavaScript的ajax //Ajax var xhr; if(window.XMLHttpRequest){ //除IE外的浏览器 xhr = new XMLHttpRequest() } ...
- Android源码分析之Looper
先来说说summary,Looper就是用来在某个线程中跑一个message loop.一个线程默认是没有message loop与之相关联的, 为了创建一个你必须在这个线程中调用Looper.pre ...
- Java线程池的实现
线程池的作用: 一个线程的周期分为:创建.运行.销毁三个阶段. 处理一个任务时,首先创建一个任务线程,然后执行任务,完了还要销毁线程.而线程只有处于运行状态的时候,才是真的在处理我们交给它的任务,这个 ...
- 测试管理_下属谈话[持续更新ing]
作为测试部门的管理者,在工作绩效评定.工作安排.工作问题提出等时候,都需要与下属进行面对面谈话,怎么进行有效的谈话,这是一个值得思考和锻炼的问题. 谈话的内容: 谈近阶段工作的回顾 谈工作中的困难(是 ...
- [转]个人源码管理:如何在本机配置自己的SVN Repository (图解)
本文转自:http://blog.csdn.net/wikijava/article/details/6245588 Repository 即源码的集中存放处,所有修改后提交的源码就是保存在这里,并在 ...
- MySQL 存储过程实例 与 ibatis/mybatis/hibernate/jdbc 如何调用存储过程
虽然MySQL的存储过程,一般情况下,是不会使用到的,但是在一些特殊场景中,还是有需求的.最近遇到一个sql server向mysql迁移的项目,有一些sql server的存储过程需要向mysql迁 ...
- JAVA基础知识点:内存、比较和Final
1.java是如何管理内存的 java的内存管理就是对象的分配和释放问题.(其中包括两部分) 分配:内存的分配是由程序完成的,程序员需要通过关键字new为每个对象申请内存空间(基本类型除外),所有的对 ...
- 设计模式C#实现(二)——适配器模式
适配器模式:将一个类的接口,转换成客户期望的另一个接口.适配器让原本接口不兼容的类可以合作无间. 如果它走起路来像只鸭子,叫起来像只鸭子,那么它必定可能是一只鸭子包装了鸭子适配器的火鸡…… 最近有一个 ...