C++ 操作符重载Operator

C++可以重载大多数操作符,如算术运算符+号,-号。

位操作符<<,>>

下标符号\[\]等都可以重载。

重载的意思,是让这些符号,按你定义的行为来执行代码,但是这种自定义,是有限制的,必须有一个自定义类(结构体等也行)参与其中。

比如,int a,int b;然后a+b,这种情况的+号是不能重载的。

所以通常的用法是,编写一个类,然后重载操作符,比如:

cpp 复制代码
#include <iostream>

using namespace std;

class myInt {
public:
	int value;
	int operator+(int num) {
		return value + num;
	}
};

int main()
{
	myInt a;
	a.value = 5;

	int res = a + 18;

	cout << res << endl;
}

输出结果:

结果为23,可见重载执行正常,否则类对象是不支持+号运算的。

在类中可以看到这这个代码:

cpp 复制代码
	int operator+(int num) {
		return value + num;
	}

operator+表示重载+号运算符, 最前面的int开头,是表示返回值类型,参数(int num),表示+号右侧类型。

那么像这种在类里面通过成员函数的方式重载的,默认左侧为此类的对象参数。

也就是说int res = a + 18; +号左侧a为myInt对象,右侧为int类型,触发重载,调用重载函数中的代码。

如果我重载了+号,那么在程序中,+号是随处可见的,那么这种情况下,不会引起混乱吗?

其实,你可以把这种重载相当于你自定义了一个另类函数。

那么道理跟函数重载一样,你调用同名函数,为什么不会引起混乱,那是因为有参数类型限制。

确保调用到指定的函数。

操作符重载也是一样,有类型限制的,你调用的是哪个类对象的+号,它就会执行相应的这个类对应的重载代码。

那么我们可以推测,int res=a+18,那么如果int在左侧,myInt在右侧。即int res=18+a;

是不合法的,没有与之匹配的重载,所以这里有着严格的要求,包括+号是二元操作符,只能有左右两个参数,你不能像这样int operator+(int num,int num1) 去定义它。

如果我要实现int res=18+a该怎么做?

重载必须定义为全局或者友元函数才可实现,因为如果是成员函数的话,是要求操作符左侧必须为类对象本身。

而全局和友元则可灵活的指定顺序,如:

全局函数重载方式:

cpp 复制代码
// 全局函数:支持 int + myInt
int operator+(int num,  myInt m) {
	return num + m.value;
}

注意将函数代码放在类定义后面,否则认不到myInt类型,没有声明的话。

这样,就会支持18+a的重载,可以看到有两个参数,因为不是成员函数,所以需要显式指定两个参数,int num为左侧类型,myInt m为右侧类型,这样当int res=18+a,符合全局函数重载描述,即根据参数类型调用指定的重载。执行全局函数的代码。

当然上面只是示例说明,一般我们建议写成友元函数,像这样:

cpp 复制代码
#include <iostream>

using namespace std;

class myInt {
public:
	int value;
	int operator+(int num) {
		return value + num;
	}

	// 友元函数:int + myInt
	friend int operator+(int num, myInt m)
	{
		return num + m.value;
	}
		
};

int main()
{
	myInt a;
	a.value = 5;

	int res = 18 + a;

	cout << res << endl;
}

结果:

下标操作符重载

接下来我们来重载\[\]这个操作符,巩固一下我们的学习成果,\[\]也是一个二元操作符,它的左侧是类对象,右侧是索引。知道了这个,我们就好重载了,如下:

cpp 复制代码
#include <iostream>

using namespace std;

class myInt {
public:
	int a;
	int b;

	int operator[](int index) {
		if (index == 0) return a;
		if (index == 1)  return b;
		else return 0;

	}


};

int main()
{
	myInt mya;
	mya.a = 10;
	mya.b = 100;

	cout << mya[0] << endl;
	cout << mya[1] << endl;

}

结果:

关键语句:

cpp 复制代码
	int operator[](int index) {
		if (index == 0) return a;
		if (index == 1)  return b;
		else return 0;

	}

重载\[\]操作符,如果索引为0,返回a,为1返回b。

运行结果是10和100,说明执行正常。

但这里,只是读取值,一般像\[\]这种用法,除了读取值,还需要写入值。

而我这里并没有这样的功能,那要怎么实现呢?

我们需要返回的值,不是按值传递,而是类似于指针的形式,比如mya0返回的是个指针:

cpp 复制代码
#include <iostream>

using namespace std;

class myInt {
public:
	int a;
	int b;

	int * operator[](int index) {
		if (index == 0) return &a;
		if (index == 1)  return &b;
		
	}
};

int main()
{
	myInt mya;
	mya.a = 10;
	mya.b = 100;

	*(mya[0]) = 1000;
	cout << *(mya[0]) << endl;
	cout << *(mya[1]) << endl;

}

结果:

可以正常赋值和取值,但是这种实现,使用起来需要加上*操作符,会变得很奇怪。

所以最好的方法是,通过&这个引用操作符, 返回类型为int &,给变量取别名的方式,如下:

cpp 复制代码
#include <iostream>

using namespace std;

class myInt {
public:
	int a;
	int b;

	int & operator[](int index) {
		if (index == 0) return a;
		if (index == 1)  return b;
		
	}
};

int main()
{
	myInt mya;
	mya.a = 10;
	mya.b = 100;

	mya[0] = 1000;
	cout << mya[0]<< endl;
	cout << mya[1]<< endl;

}

结果输出1000和100,正常,这样看起来就顺眼多了。

相关推荐
悠仁さん5 小时前
【C++】AVL 树
c++
wuminyu5 小时前
JVM规范学习总结:解释器与JIT编译器如何处理JVM字节码
java·linux·c语言·jvm·c++
小徐不徐说6 小时前
序列化与反序列化:把 C++ 对象可靠地保存下来
开发语言·数据库·c++·php
ragnwang6 小时前
Notes: Python pybind11 import C++ module
开发语言·c++·python
Wang's Blog6 小时前
Java 项目实战: 交友项目 - 搜索附近的功能概述和分析
java·开发语言·交友
骑着蜗牛撵大象3276 小时前
大模型 Agent 的沙箱护栏:gVisor 隔离、出口白名单与审计闭环
java·开发语言·jvm·安全·agent沙箱·gvisor·microvm
Dxy12393102167 小时前
JS DES 加密详解
开发语言·javascript·arcgis
充值内卷7 小时前
我给桌面加了个鱼缸:C++ 写后端,WebView2 里养一座 Three.js 小岛
开发语言·javascript·c++
云和数据.ChenGuang8 小时前
深入解析 Python 的 dir():从用法到 CPython 源码实现
开发语言·人工智能·python·langchain
nice_lcj5208 小时前
深入理解 Java 反射:从 Class 对象到方法调用(含性能实测 + 迷你 IOC 实战 + 面试考点)
java·开发语言·后端·面试