C++运算符重载

C++ 运算符重载

C++中预定义的运算符的操作对象只能是基本数据类型。

但实际上,对于许多用户自定义类型(例如类),也需要类似的运算操作。

因此可以重定义或重载大部分 C++ 内置的运算符。这样,您就能使用自定义类型的运算符。

运算符重载是通过创建运算符函数实现的,运算符函数定义了重载的运算符将要进行的操作。运算符函数的定义与其他函数的定义类似,唯一的区别是运算符函数的函数名是由关键字operator和其后要重载的运算符符号构成的。

重载的运算符是带有特殊名称的函数,函数名是由关键字 operator 和其后要重载的运算符符号构成的。与其他函数一样,重载运算符有一个返回类型和一个参数列表。

一. +运算符重载

重载+运算符,我们可以给+重新定义其含义。

例如:

// 使用内置的+运算符操作进行int类型的运算
int a = 10;
int b = 20;
int c = a + b; // 结果为30

如果我们使用+运算符来运算我们的自定义数据类型时,需要重载+运算符才可以。

举个例子:有个我们自定义的数据类型Person,有height和weight两个属性

class Person
{
public:

	int height;	// 身高
	int weight;	// 体重

	Person(int height, int weight) 
	{
		this->height = height;
		this->weight = weight;
	}
};

我们定义两个对象p1和p2;

Person p1(10,10);	// 将p1的两个属性设置为10,10
Person p2(20,20);	// 将p2的两个属性设置为20,20

如果我们想对p1和p2进行height和weight的分别相加的运算通过,我们需要:

int heigt = p1.height + p2.height;
int weight = p1.weight + p2.weight;

当然我们也可以通过重载+运算符进行运算:

有两种方式:

  • 成员函数重载
// 成员函数重载+
Person operator+(Person &p)
{
    Person temp;	// 创建一个Person对象temp,用来临时存储 两个对象相加的值
    temp.height = this->height + p.height;
    temp.weight = this->weight + p.weight;
    return temp;	// 返回 temp,为Person类型的对象
}

成员函数重载的本质

cout << p1.operator+(p2).height << endl;

可以简写为:cout << (p1 + p2).height << endl;

  • 全局函数重载1
// 全局函数重载+
Person operator+(Person& q, Person& p)
{
	Person temp;
	temp.height = q.height + p.height;
	temp.weight = q.weight + p.weight;
	return temp;
}

这种只能两个两个进行操作,在VS2019以后,重载的+运算符的结果是一个纯右值,不能作为左值进行计算,所以多个类的实例连续相加会报错。只能两两相加。

  • 全局函数重载2
//在全局区开辟一段内存,不在全局函数中开辟,防止函数执行完成后系统回收
Person temp;
// 全局函数重载+
Person& operator+(Person& q, Person& p)
{
	temp.height = q.height + p.height;
	temp.weight = q.weight + p.weight;
	return temp;
}

返回引用,同时注意不要在栈中开辟空间。

这种可以实现链式操作。

全局函数重载的本质

cout << operator+(p1, p2).height << endl;

可以简写为:cout << (p1 + p2).height << endl;

// 输出验证一下
	cout << (p1 + p2).height << endl;
	cout << (p1 + p2).weight << endl;

如果有两个以上的对象进行操作:链式操作

Person p1(10, 10);	// 将p1的两个属性设置为10,10
Person p2(20, 20);	// 将p2的两个属性设置为20,20
Person p3(30, 30);	// 将p3的两个属性设置为30,30
Person p4(40, 40);	// 将p3的两个属性设置为40,40
Person p5(50, 50);	// 将p3的两个属性设置为50,50
// 输出验证一下
cout << (p1 + p2 + p3 + p4 + p5).height << endl;	//输出 150(10+20+30+40+50)
cout << (p1 + p2 + p3 + p4 + p5).weight << endl;	//输出 150(10+20+30+40+50)

由此可见,适当的使用运算符重载可以使程序更加简洁,方便编程。

-运算符的重载与+类似,可以根据自己的需要进行编程。

二. 左移运算符>>重载

作用:可以输出自定义类型数据

还是以上一个代码为例子

重载<<同样有两种方法:成员函数和全局函数。分别写一下:

  1. 成员函数重载:

要弄清成员函数重载的本质,即为对象调用成员函数,对象.函数名(参数);

比如我们想重载左移运算符用来格式化输出 对象的 height 和 weight

一开始可以这样写:

// 成员函数重载左移运算符
void operator<<(ostream& cout)
{
	cout << "p的height= " << this->height << " p的weight= " << this->weight;
}

调用时:

p1.operator<<(cout);	// 本质调用
p1 << cout;				// 简化之后

这显然不符合我们的使用习惯。所以要用第二种方法:全局函数重载。

  1. 全局函数重载
// 将全局函数声明为友元函数,可以访问类中的私有成员
friend void operator<<(ostream& cout, Person& p);
// 全局函数重载左移运算符
void operator<<(ostream& cout, Person& p)
{
	cout << "height= " << p.height << " weight= " << p.weight;
}

调用时:

operator<<(cout, p1);	// 本质调用
cout << p1;				// 简化之后

用这两种方法,我们成功的将左移运算符重载,使其有了我们想要的功能。

但发现,如果我们想进行链式操作,程序会报错。究其原因,是因为我们的返回类型为void,进行链式操作时,两种类型不一致,所以无法进行操作。稍作修改,将返回类型改为cout的返回类型就可以,也就是ostream

全局函数重载左移<<运算符:

在类中将全局函数声明为友元函数

friend ostream& operator<<(ostream& cout, Person& p);
// 全局函数重载左移运算符
ostream& operator<<(ostream& cout, Person& p)
{
	cout << "height= " << p.height << " weight= " << p.weight;
	return cout;
}

这样一来,我们便可以实现链式操作了。

在运算符重载时,实现链式操作的关键就是注意返回类型,要根据实际情况来看,重载函数的返回值要跟后面进行操作的对象为同一类型,具体情况具体分析。

三. 关系运算符重载

同样是两种方法。以>为例。

  1. 成员函数重载
// 成员函数重载
bool operator>(Person& p)
{
	if (this->height > p.height)
		return true;
	else
		return false;
}

调用时:

bool result1 = p2.operator>(p1);	// 本质
bool result2 = p1 > p2;				// 简化
cout << result1 << endl;
cout << result2 << endl;
  1. 全局函数重载
friend bool operator>(Person& p1, Person& p2);	// 将全局函数声明为友元函数
// 全局函数重载
bool operator>(Person& p1, Person& p2)
{
	if (p1.height > p2.height)
		return true;
	else
		return false;
}

调用时:

bool result1 = p1 > p2;				// 简化
bool result2 = operator>(p1,p2);	// 本质
cout << result1 << endl;
cout << result2 << endl;

关于运算符的重载就先写到这里,最重要的是了解本质,就是用成员函数或者是全局函数重新定义一下该运算符的功能,然后去调用成员函数或者是全局函数。

目前就先写这么多吧,其他几种运算符的重载应该是大同小异,有机会的话会更加深入的学习一番。

posted @   ProEmon  阅读(90)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· winform 绘制太阳,地球,月球 运作规律
· AI与.NET技术实操系列(五):向量存储与相似性搜索在 .NET 中的实现
· 超详细:普通电脑也行Windows部署deepseek R1训练数据并当服务器共享给他人
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 上周热点回顾(3.3-3.9)
点击右上角即可分享
微信分享提示