[cpp] 重载运算符规律总结
重载运算符是对正常函数的语法美化.没给语言增加任何基本的东西,但改善了可理解性并降低维护费用.当用户需要时,就应该使用运算符重载,但应该仅仅以用户熟悉的语义方式来使用它。
1. 重载规则
不能重载的运算符: . 和 .* 和 ?: 和 :: 和 sizeof 和 typeid
重载运算符有两种基本选择: 类的成员函数或者友元函数, 建议规则如下:
运算符 |
建议使用 |
所有一元运算符 |
成员函数 |
= () [] -> |
必须是成员函数 |
+= -= /= *= ^= &= != %= >>= <<= , 似乎带等号的都在这里了. |
成员函数 |
所有其它二元运算符, 例如: –,+,*,/ |
友元函数 |
2. 参数和返回值
当参数不会被改变,一般按const引用来传递(若是使用成员函数重载,函数也为const).
对于返回数值的决定:
1) 如果返回值可能出现在=号左边, 则只能作为左值, 返回非const引用。
2) 如果返回值只能出现在=号右边, 则只需作为右值, 返回const型引用或者const型值。
3) 如果返回值既可能出现在=号左边或者右边, 则其返回值须作为左值, 返回非const引用。
3. 几个例子
3.1 二元运算法建议使用友元函数重载,与内部类型的操作相似
1: class Integer {
2: int _val;
3: public:
4: Integer(int val = 0) : _val(val) {}
5:
6: // 二元运算符重载为成员函数
7: const Integer operator+(const Integer& i) const {
8: return Integer(_val + i._val);
9: }
10: // 二元运算符重载为友元函数
11: friend const Integer operator-(const Integer& ,const Integer&);
12: };
13: const Integer operator-(const Integer& l,const Integer& r) {
14: return Integer(l._val-r._val);
15: }
16:
17: Integer a(40), b(12);
18:
19: a+b;
20: a+1; // 正确, 左操作数为Integer对象, +按照Integer的成员函数解析右操作数为1, 进行自动类型转换
21: 1+a; // 错误, 左操作数为1, +按照常规操作符解析, 而右操作符为Integer对象,1无法进行转化
22: a-b; // 正确
23: a-1; // 正确
24: 1-a; // 正确, 左操作数为1, 而右操作符为Integer对象,-作为Integer的一个友元函数,1被转化为Integer对象
1) 在上面的代码中, 二元操作符+作为成员函数重载,在进行形如1+a之类的调用无法正确解析。二元操作符-作为友元函数重载,使用方法与常规的-号操作符的操作类似。
2) 如上的运算符重载, 运算符的运算结果必定位于=号的右边, 返回的是一个右值, 返回const型值。
3.2 ++与--运算符重载
1) operator++有两种形式, 后缀形式i++, 它重载时有一类型为int的虚参。前缀形式++i,它重载时没有虚参.operator--情况类似。
2) 后缀形式(i++,i--)返回原状态的拷贝(或者返回void), 前缀形式(++i, --i)通过引用返回*this。这是为了和内部类型保持一致.
前缀版本(++i,--i)返回的是一个左值, 也就是返回一个非const引用.
后缀版本(i++,i--)返回的是一个右值, 也就是返回一个const型值
1: class Example{
2: public:
3: Example(int i,int j) { _x = i; _y = j;}
4: // 前缀形式(++i)重载的时候没有虚参,通过引用返回*this,也就是返回变化之后的数值
5: const Example& Example::operator++ () {
6: ++_x;
7: ++_y;
8: return *this;
9: }
10: // 后缀形式(i++)重载的时候有一个int类型的虚参, 返回原状态的拷贝
11: const Example Example::operator++ (int) {
12: Example tmp(*this);
13: ++_x;
14: ++_y;
15: return tmp;
16: }
17: int _x, _y;
18: };
19:
3.3 重载下标运算符[]
1: class Array {
2: public:
3: Array(int size) : _size(size) { _val = new int[_size];}
4: int& operator[] (int index) { return _val[index]; }
5: const int& operator[] (int index) const { return _val[index]; }
6: private:
7: int _size;
8: int* _val;
9: };
10: Array array_a(10);
11: array_a[0] = 1; // []的重载版本有非const版本
3.4 重载输入输出操作符
由于>>与<<操作符总是要被赋值,必须返回一个左值。
1: class A
2: {
3: private:
4: int a,b;
5: public:
6: A(int na = 0, int nb = 0):a(na), b(nb){}
7: friend istream& operator>>(istream& is, A& aa);
8: friend ostream& operator<<(ostream& os, const A& aa);
9:
10: };
11: ostream& operator<<(ostream& os, const A& aa) {
12: os << aa.a << " " << aa.b;
13: return os;
14: }
15:
16: istream& operator>>(istream& is, A& aa) {
17: is >> aa.a >> aa.b;
18: return is;
19: }
转载于:https://www.cnblogs.com/alex-tech/archive/2011/03/27/1997045.html
[cpp] 重载运算符规律总结相关推荐
- 4.0 C++远征:重载运算符
目录 重载运算符 四.重载运算符 1.一元运算符重载 2.二元运算符重载 重载运算符 四.重载运算符 概念 : 给原有运算符赋予新功能. 本质 : 函数重载. 关键字 : operator ...
- 【C++ 语言】面向对象 ( 函数重载 | 运算符重载 | 运算符重载两种定义方式 | 拷贝构造方法 | RVO 优化 | NRVO 优化 )
文章目录 函数重载 运算符重载 ( 类内部定义云算符重载 ) 运算符重载 ( 类外部定义运算符重载 ) 可重载的运算符 拷贝构造方法 编译器优化 ( RVO 优化 | NRVO 优化 ) 完整代码示例 ...
- 重载函数和重载运算符
C++允许在同一个作用域中的某个函数和运算符指定多个定义,分别称为函数重载和运算符重载. 重载声明是指一个与之前已经在该作用域内声明过的函数或方法具有相同名称的声明,但他们的参数列表和定义(实现)不相 ...
- c++重载++运算符_C ++运算符重载| 查找输出程序| 套装3
c++重载++运算符 Program 1: 程序1: #include <iostream> using namespace std; class Test { public: int A ...
- 第八周——重载运算符——项目一(1)实现复数的+-*/
问题及代码: /* *Copyright (c) 2014,烟台大学计算机学院 *All rights reserved. *文件名称:lily.cpp *作者:李莉 *完成日期:2015年4月2日 ...
- c++的构造函数赋值函数重载运算符等
文章目录 一.前言 二.正文 1.拷贝构造函数 2.赋值函数 3.operator()() 重载()运算符 4.类中方法前面的template 5.类实例化的方式 (1)调用构造函数实例化和指针实例化 ...
- C++ | C++ 重载运算符和重载函数
文章目录 C++ | C++ 重载运算符和重载函数 C++ 重载运算符和重载函数 C++ 中的函数重载 实例1: C++ 中的运算符重载 实例2: 可重载运算符/不可重载运算符 运算符重载实例 运算符 ...
- 36 CPP typeid运算符和type_info类
36 CPP typeid运算符和type_info类 type_info 重载了==和!=运算符,用于对类型进行比较 注意: 1 type_info类的构造函数是private属性,也没有拷贝构造函 ...
- C++ 实现字符串类(重载运算符)
CNString.h: #include <iostream> #include <cstring>#ifndef CNSTRING_H #define CNSTRING_H ...
最新文章
- 程序员请收好:10个非常有用的Visual Studio Code插件
- i++ 和++i的区别
- 特征工程-统计数据特征
- 论文笔记:N-BEATS: NEURAL BASIS EXPANSION ANALYSIS FORINTERPRETABLE TIME SERIES FORECASTING
- 【三维激光扫描】实验02:StonexSiScan新建项目、加载点云数据
- CSS--居中方式总结
- Series与DataFrame数据类型操作基础
- Agc019_F Yes or No
- 滴滴顺风车再调整服务时间:男女用户一视同仁
- vue3 el-form表单验证 自定义校验
- 查询所有_学会DSUM函数,轻松搞定所有的数据查询与数据求和
- 终结者:使用slf4j+log4j完美构建日志
- JZOJ.5325【NOIP2017模拟8.21】九九归一
- Easyui按钮图标
- oracle常用查询语句
- hdu1411知六边长求四面体体积
- re学习笔记(25)BUUCTF-re-[2019红帽杯]easyRE
- 网页加速之Chromium 预加载 Prerendering
- python心率检测
- 论文翻译:2020_TinyLSTMs: Efficient Neural Speech Enhancement for Hearing Aids
热门文章
- 越权操作(文件读取漏洞)
- bzoj 1801: [Ahoi2009]chess 中国象棋 bzoj 4806: 炮
- 弦图与完美消除序列(bzoj 1006: [HNOI2008]神奇的国度)
- 静态RAM(1K X 4位)2114原理介绍(抄原理图)
- centos配置ssh免密码登录
- 【shell】echo不显示变量中的多个空格
- python基本定制之__new__, __init__
- uva 540 (Team Queue UVA - 540)
- RANDOM模块:PYTHON获取随机数
- C#中使用反射遍历一个对象属性和值以及百分数