C++运算符重载

  • 重载运算符“+”
    • 第1个const
    • 第2个const
    • 第3个const
  • 重载运算符“-”
  • 重载运算符“-”(与上面的含义不同)
  • 重载运算符 “+=” 与 “-=”
  • 重载运算符 “==” 与 “!=”
  • 重载运算符 “++” 与 “--”
  • 重载 “<<" 与 “>>”
  • 完整源代码

C++里面的运算符重载细节特别多,这里用一个 Point 类来演示一下C++的运算符重载。(需要理解友元函数,指针,引用等概念

如下是一个 Point 类,只有 m_x ,m_y 两个私有成员变量
拥有一个构造函数,接收了 x,y 两个参数,
diplay() 方法用来展示 Point 对象的属性。

class Point {private:int m_x, m_y;
public:Point(int x, int y) : m_x(x), m_y(y) {} // 参数列表初始化构造函数void display() {cout << "(x1=" << m_x << ", x2=" << m_y << ")" << endl;}
}

重载运算符“+”

class Point {int m_x, m_y;
public:Point(int x, int y) : m_x(x), m_y(y) {}void display() {cout << "(x1=" << m_x << ", x2=" << m_y << ")" << endl;}// 第一个const表示返回值是个常量,用来防止 (p1+p2)=Point(10,20); 这种赋值// 括号内第二个const表示传入的参数可以接收const也可以接收非const// 第三个const表示常量可以调用该函数  // 具体见下面的分析。const Point operator+(const Point &point) const {return Point(m_x + point.m_x, m_y + point.m_y);}
}
const Point operator+(const Point &point) const{return Point(m_x + point.m_x, m_y + point.m_y);
}

这个函数定义有 3 个const,分别理解一下它们的意思。

第1个const

第一个const,表示返回值是常量,什么意思呢?我们来看一段C++代码。

int a = 1;
int b = 2;
(a + b) = 5; // 在C++中不允许如此做,会报错

上述这段代码在C++中是不允许的,a,b都是变量,但是无法对(a+b)进行赋值

Point p1 = (10, 20);
Point p2 = (20, 30);
(p1 + p2) = Point(40, 50); // 如果不加第1个const,则这里不会报错

因此,对我们自定义的 Point 类来说,上面这段代码是应当是不允许的。解决方案是,我们将 (p1+p2) 的结果看作常数,常数不允许被赋值。因此,在重载操作数+的过程中,我们需要将返回值写成 const Point

第2个const

const Point operator+(const Point &point) const{//code...
}

第2个 const ,即括号里的const Point &point,这个 const 是什么意思呢?
这个 const 是为了扩大接受参数的范围。我们依旧来看一段C++代码。

int a = 1;  // 变量
const int b = 2; // 常数
// b = 3; // 会报错,常数不可修改
int c = a + b ;  // 常数不可修改,但是可以做运算
// 注意,这里a是变量,b是常数

上面这段代码表示,+ 号可以接收常数参数, 想想也很好理解,常数不可修改,但是可以参与运算。

Point p1 = (10, 20);
const Point p2 = (20, 30);
Point p3 = p1 + p2; // 不加第2个const,这里会报错,因为p2是常数
// 注意,这里p1是变量,p2是常量,由于重载了“+”
// 上一句代码等同于 p1.operator+(p2);
// 将p2视为了参数,即将常量视为参数。

对于我们自定义的类来说,上面这段代码应当是被允许的。我们需要在重载操作数+的过程中,给接收的参数加上 const,就可以同时接受 const参数 与 非const参数,扩大了接受参数的范围。

第3个const

const Point operator+(const Point &point) const{//code...
}

第3个 const,即括号后面的 const,它的作用是 使得该函数可以被 const 对象所调用。直接看 Point 的操作。

const Point p1 = (10, 20);
Point p2 = (20, 30);
Point p3 = p1 + p2; // 不加第3个const,这里会报错,因为p1是常数
// 注意,这里p1是常量,p2是变量,由于重载了“+”
// 上一句代码等同于 p1.operator+(p2);
// 由p1调用的operator+函数,因此调用该函数的是个常数。

请仔细对比第2个const与第3个const的区别,仔细看注释!可能有点容易混淆!
p1对象是个常量,Point p3 = p1 + p2; 实际上等价于 p1.operator+(p2);,实际上是拿常量p1调用了函数,因此这个函数必须可以被常量调用,这就是第3个const的作用。

重载运算符“-”

重载运算符 “-” 与 “+” 思路一模一样,同上。

const Point operator-(const Point &point) const{return Point(this->m_x - point.m_x, this->m_y - point.m_y);
}

重载运算符“-”(与上面的含义不同)

我们来看一段C语言代码,理解一下这个“-”的含义是什么。

int a = 2;
int b = -a;

知道了吧,这个“-”,是放在变量前面,让他的值变成相反数。
但是要注意这是个单目运算符,是不需要传函数参数的

const Point operator-() const {return Point(-m_x, -m_y);
}

重载运算符 “+=” 与 “-=”

Point& operator+=(const Point &point) { // 返回值要注意this->m_x += point.m_x;this->m_y += point.m_y;return *this;
}Point& operator-=(const Point &point) { // 返回值要注意this->m_x -= point.m_x;this->m_y -= point.m_y;return *this;
}

这里说一下返回值为什么是 Point &,这是一个引用对象。我们看一段C++代码。

int a = 1;
(a += 1) = 2;

在 C++ 中,(a+=1)是允许被赋值的,我们可以理解为 (a+=1) 的返回值依旧是一个变量
务必与之前的(a+b) = 3区分开,这个式子是不允许的,因此(a+b)的返回值被我们理解为常量,这也是之前3个const之第1个const的原因。
那么就可以理解为什么要用 Point & 来接受参数了。其实还有一个好处,即可以少创建一个对象。(这里不做详细说明)。

重载运算符 “==” 与 “!=”

bool operator==(const Point &point) const {return point.m_x == this->m_x && point.m_y == this->m_y;
}
bool operator!=(const Point &point) const {return point.m_x != this->m_x || point.m_y != this->m_y;
}

这两个应该很好理解,不做过多说明。

重载运算符 “++” 与 “–”

众所周知,C++中的 ++ 与 – 分为前缀后缀两种,如下。

int a;
a++;
++a;

这两种操作符是需要分别重载的,那么如何区分呢?主要看传参入的参数,如下。

Point& operator++() {} // 默认代表重载++a
const Point operator++(int) {} // 传入参数写int代表a++,固定格式。

Point& 与 const 的分析方法与最开始所讲差不多,理解了那个必然能理解下面的的代码。

Point& operator++() { // ++a++m_x;++m_y;return *this;
}
const Point operator++(int) { // a++Point old = Point(m_x, m_y);m_x++;m_y++;return old;
}
Point& operator--() { // --a--m_x;--m_y;return *this;
}
const Point operator--(int) { // a--return Point(m_x--, m_y--);
}

重载 “<<" 与 “>>”

注意,重载 “<<”,由于格式是cout << a;,"<<“符号左边的参数必须接收"cout”,因此不可以当作成员函数来重载,必须写在全局区,可以通过与友元函数相结合来达到目的

重载">>",格式是cin >> a;,">>"符号左边的参数必须接收 “cin”,同样不可以当作成员函数来重载,必须写在全局区,通过与友元函数来达到目的。
并且,由于接收的参数是会修改的,不能加 const 修饰。

class Point {// 重载 "<<" 与 ">>" 的友元函数friend ostream &operator<<(ostream &cout, const Point &point);friend istream &operator>>(istream &cin, Point &point);int m_x, m_y;
public:Point(int x, int y) : m_x(x), m_y(y) {}
}
// 重载 "<<"
ostream &operator<<(ostream &cout, const Point &point) { // 重载 "<<",由于结果是 cout << a; 不可以当作成员函数来重载,必须写在全局区。cout << "(x1=" << point.m_x << ", x2=" << point.m_y << ")";return cout;
}
// 重载 ">>"
istream &operator>>(istream &cin, Point &point) { // 重载">>",由于接收的参数会修改,不能加const修饰cin >> point.m_x >> point.m_y;return cin;
}

完整源代码

#include<iostream>
using namespace std;class Point {//friend Point add(Point, Point); // 友元函数//friend Point operator+(const Point &, const Point &);friend ostream &operator<<(ostream &cout, const Point &point);friend istream &operator>>(istream &cin, Point &point);int m_x, m_y;
public:Point(int x, int y) : m_x(x), m_y(y) {}void display() {cout << "(x1=" << m_x << ", x2=" << m_y << ")" << endl;}const Point operator+(const Point &point) const { // 第一个const表示返回值是个常量,用来防止 (p1+p2)=Point(10,20); 这种赋值return Point(m_x + point.m_x, m_y + point.m_y);// 括号内第二个const表示传入的参数可以接收const也可以接收非const}                                                   // 第三个const表示常量可以调用该函数const Point operator-(const Point &point) const{return Point(this->m_x - point.m_x, this->m_y - point.m_y);}Point& operator+=(const Point &point) { // 返回值要注意this->m_x += point.m_x;this->m_y += point.m_y;return *this;}bool operator==(const Point &point) const {return point.m_x == this->m_x && point.m_y == this->m_y;}bool operator!=(const Point &point) const {return point.m_x != this->m_x || point.m_y != this->m_y;}const Point operator-() const {return Point(-m_x, -m_y);}/* // 这样写也可以达到效果,但是会多创建一个对象,不如下面的写法好Point operator++() { // ++areturn Point(++m_x, ++m_y);}*/Point& operator++() { // ++a++m_x;++m_y;return *this;}/*const Point operator++(int) { // a++return Point(m_x++, m_y++);}*/const Point operator++(int) {Point old = Point(m_x, m_y);m_x++;m_y++;return old;}Point& operator--() { // --a--m_x;--m_y;return *this;}const Point operator--(int) { // a--return Point(m_x--, m_y--);}
};ostream &operator<<(ostream &cout, const Point &point) { // 重载 "<<",由于结果是 cout << a; 不可以当作成员函数来重载,必须写在全局区。cout << "(x1=" << point.m_x << ", x2=" << point.m_y << ")";return cout;
}istream &operator>>(istream &cin, Point &point) { // 重载">>",由于接收的参数会修改,不能加const修饰cin >> point.m_x >> point.m_y;return cin;
}//const Point operator+(const Point &p1, const Point &p2) { // 建议加const,并且设定为引用类型
//  return Point(p1.m_x + p2.m_x, p1.m_y + p2.m_y);
//}int main() {const Point p1(10, 20);Point p2(10, 30);Point p3(30, 40);cin >> p2 >> p3;cout << p2 << p3 << endl;//Point p4 = --p2 + Point(10, 20);//Point p4 = ++p2 + Point(10, 20);//p4.display(); // p2++ 20 50    ++p2 21 51//p2.display(); // 11 31/*p2++;(++p2) = p1;(++p2)++;*///(p2++) = p1; //不可以//p2.display();//Point p4 = -p3;//p4.display();//Point p4 = p1 + p2 + p3;//p1 += p2;//(p1 += p2)+=p3;//p1.display();//cout << (p1 == p2) << endl;//p4.display();//Point p4 = add(p1, p2);//p4.display();return 0;
}

【C++】运算符重载关于const的分析(超详细)相关推荐

  1. Google Earth Engine——生物多样性方面案例(在线获取采样点数据)分析超详细的案例介绍(1.5万字)

    生成采样数据 1简介 2背景 2.1关于数据

  2. C++ 重载运算符 继承 多态 (超详细)

    (一)重载运算符: (1)声明与定义格式 一般是类内声明,类外定义,虽然可以在类内定义,但 写前面堆一堆不好看!!! 类内声明: class Demo {返回值类型 operator 运算符(形参表) ...

  3. c++中 运算符重载 const 函数

    概要 本篇文章主要内容是关于运算符重载,然后在最后提了一下 const修饰函数时的状况.后面会补上一个日期类的定义. 文章目录 概要 赋值运算符的重载 = 号的重载 i++ 和 ++i 前置与后置++ ...

  4. C++运算符重载(超全)

    C++运算符重载 1) 运算符重载的本质为函数重载,但有一定的规则需要遵循.[1] (1)重载运算符时,运算符的运算顺序和优先级不变,操作数个数不变. (2)不能创造新的运算符,只能重载C++中已有的 ...

  5. 运算符重载(超详细)

    文章目录 运算符重载 1.运算符重载是什么 2.运算符重载实例 3.运算符重载操作原理 4.重载限制 5.使用其他运算符具体实现 运算符重载 1.运算符重载是什么 使对象操作更美观的技术. 运算符重载 ...

  6. inline函数返回值_C++知识补充-指针,const,函数指针,指针数组,运算符重载

    嵌入式Linux:C++ 面试准备珍藏版本​zhuanlan.zhihu.com 明月照我心:123道c++笔试题汇总(含答案)​zhuanlan.zhihu.com 阿贵:常见C++笔试面试题整理​ ...

  7. [转载] python 运算符重载有什么用_Python运算符重载用法实例分析

    参考链接: Python运算符重载 本文实例讲述了Python运算符重载用法.分享给大家供大家参考.具体如下: 在Python语言中提供了类似于C++的运算符重在功能: 一下为Python运算符重在调 ...

  8. C++ STL: 超详细 容器 deque 以及 适配器queue 和 stack 源码分析

    文章目录 前言 deque 实现 deque类 _Deque_iterator 类 deque 的元素插入 insert函数 deque如何模拟空间连续 queue 实现 stack 的实现 前言 C ...

  9. Java为什么不提供运算符重载?

    从C ++到Java,一个显而易见的未解决问题是Java为什么不包括运算符重载? 不是Complex a, b, c; a = b + c;吗Complex a, b, c; a = b + c; C ...

最新文章

  1. python编程和plc哪个好-plc和python
  2. GetDiskFreeSpace 和 GetDiskFreeSpaceEx
  3. putty颜色设置|securecrt颜色设置|windows命令行颜色设置
  4. docker 不包含依赖 打包_Docker容器技术(概念篇)
  5. 无法打开包括文件: “corecrt.h”: No such file or directory
  6. textview 复制粘贴_Android TextView使用剪贴板复制粘贴
  7. 阶段3 2.Spring_10.Spring中事务控制_4 spring中事务控制的一组API
  8. vc2013 调用大漠插件例子
  9. [Ansys Workbench] 平面对称斜拉桥的模态分析
  10. JFreechart中文在AIX下显示方框解决方法
  11. Mocking with (and without) Spring Boot
  12. 国内首部创业纪实电影《燃点》进校园:如何靠近成功的2%
  13. ERLANG日期与时间
  14. GIS地图坐标系转换方法,快快收藏
  15. 记载一次cesium加载近景天空盒的例子
  16. vue webapp之music(十一) 歌手数据处理和singer类的封装
  17. 第十周博文作业-小学生考试系统(1)
  18. iphone设置铃声
  19. easybuy源码_easybuy数据库设计
  20. mac下直接打开finder的快捷键

热门文章

  1. 直播电商要处理好五个关系
  2. 盘点劳务公司和中介所的那些黑心套路
  3. 真正能成大事的人,往往有一个“共同特征”
  4. Merkle Patricia Tree (MPT) 以太坊merkle技术分析
  5. linux统计所有进程总共占用多少内存?
  6. sql azure 语法_将SQL工作负载迁移到Microsoft Azure:服务选择
  7. sql隐式转换_SQL Server中的隐式转换
  8. nlp中bpe_缓冲池扩展(BPE)–内存中OLTP:内存挑战
  9. sql server 面试_SQL Server审核面试问题
  10. TAOCP-1.2.10_求极大值