【C++】运算符重载

C++中的运算符重载

目录
1.重载
2.运算符
3.一般实现方式
     ~~~~      3.1成员函数实现
     ~~~~      3.2友元函数实现
4.特殊情况
     ~~~~      4.1只能用友元函数实现
     ~~~~      4.2只能用成员函数实现
     ~~~~      4.3不能重载
  ~  

1.重载

所谓运算符重载,本质上也是对函数重载。

根据不同形参类型调用首部相同的不同函数。

这是静态多态的表现。

2.运算符

指的诸如:

+-*/[]()int等。它们本质上是函数。
注意,此处提到的int是强制类型转换运算符。

3.一般实现方式

运算符重载一般有成员函数友元函数两种实现方式。

基本语法是:返回值类型 operator运算符(形参列表)
特殊地,对于类型转换运算符,无需写返回值类型,因为转换的类型已经确定了返回值类型。

(1)成员函数

E g 1 : Eg1: Eg1:重载+实现自定义整数类型Myint的数据成员x的加法。

#include<iostream>
using namespace std;

class myint
{
	int x;
public:
	myint(int x) { this->x = x; }
	//重载+
	myint operator+(myint& y)
	{
		int temp = this->x + y.x;
		myint m(temp);
		return m;
	}

	void show()
	{
		cout << "x = " << x << endl;
	}
};

int main()
{
	myint a(1), b(2), c(0);
	c = a + b;

	c.show();//输出结果为3
	return 0;
}

E g 2 : Eg2: Eg2:重载 “ + + ” “++” ++运算符实现自定义整数类型myint的前置递增运算符。

	//重载++
	myint& operator++()
	{
		x++;
		return *this;
	}

注意

1.前置递增必须返回引用

2.为了以示后置递增与前置递增的区别,后置递增需要增加占位记号

	myint operator++(int)
	{
		myint temp = *this;
		x++;
		return temp;
	}

E g 3 : Eg3: Eg3:重载myint=运算符实现连等。

	myint& operator=(myint& temp)
	{
		this->x = temp.x;
		return *this;
	}

注意

为实现连等,必须返回引用

可以在主函数调用如下:

int main()
{
	myint a(1), b(2);
	myint c(3);

	c = b = a;
	c.show();
	return 0;
}

此时输出 x = 1 x=1 x=1

既然是成员函数,除了直接用运算符调用以外,也可以使用:

a.operator=(b);

(2)友元函数

E g 4 : Eg4: Eg4:采用外部函数方法,实现 E g 1 Eg1 Eg1中的+的重载。

#include<iostream>

class myint
{
	friend myint operator+(myint& a, myint& b);
	int x;
public:
	myint(int x) { this->x = x; }
	void show() { std::cout << "x = " << x << std::endl; }
};

myint operator+(myint& a, myint& b)
{
	int temp = a.x + b.x;
	myint ans(temp);
	return ans;
}
int main()
{
	myint a(1), b(1);
	a = a + b;
	a.show();
	return 0;
}

注意

外部函数无法直接访问类内数据,要设置为友元函数,但会破坏封装性。

另外,外部函数实现重载后也可以采用函数调用的方法,如:

	myint a(1), b(1), c(5);
	c = operator+(a, b);

4.特殊情况

(1)必须使用友元函数

E g 4 : Eg4: Eg4:重载<<运算符,打印myint类型数据;要求:可以连打印多个数据。

分析

<<本质上是一个函数,当我们使用如下语句:

cout << x << endl;

本质上我们是通过对象cout调用了operatpor<<这个函数。

如果要实现连续打印,调用结束后必然还是要返回cout这个对象。

注意,cout是属于ostream类的,且全局只有这一个对象。

因此,返回值类型必须是ostream类的引用且形参中也必须如此。

如果采用成员函数实现,那么应该写为:

	ostream& operator<<(ostream& cout)
	{
		cout << x;
		return cout;
	}

这时,根据调用的顺序应该是:

int main()
{
	myint a(1);
	a << cout << endl;
	//cout << a;错误
	return 0;
}

显然不是我们期望的结果。

当然了,我们也无法在cout中重载<<,因为这已经封装好了。

因此,重载<<运算符,只能采用友元函数,如下:

#include<iostream>
using namespace std;
class myint
{
	friend ostream& operator<<(ostream& cout, myint& m);
	int x;
public:
	myint(int x) { this->x = x; }
};

ostream& operator<<(ostream& cout, myint& m)
{
	cout << m.x;
	return cout;
}
int main()
{
	myint a(1);
	cout << a << "  " << endl;
	return 0;
}

值得注意的是,此处的ostream& cout不能加const修饰。

因为输出会先进入到ostream流,再到屏幕显示,也就是会改变其属性。

因此不能加const
  ~  

(2)必须使用成员函数

C + + C++ C++规定,以下运算符只能通过成员函数来重载。

运算符含义
=赋值运算符
()函数调用运算符
[]下标运算符
->指针访问类成员的运算符
int强制类型转换运算符

=无法重载为友元函数进行解释如下:

示例如下代码,

#include<iostream>
using namespace std;
class myint
{
public:
	int x;
	myint(int x)
	{
		this->x = x;
		cout << "constructor1" << endl;
	}
	myint(){ cout << "constructor2" << endl; }

};
int main()
{
	myint a;
	a = 20;

	return 0;
}

输出为:

在这里插入图片描述

这说明语句a=20会默认去调用与右值匹配的构造函数,也就是转为了a(20)

如果我们在成员函数内重载了=

#include<iostream>
using namespace std;
class myint
{
public:
	int x;
	myint(int x)
	{
		this->x = x;
		cout << "constructor1" << endl;
	}
	myint(){ cout << "constructor2" << endl; }
	myint& operator=(int x)
	{
		this->x = x;
		cout << "operator=" << endl;
		return *this;
	}
};

int main()
{
	myint a;
	a = 20;
	return 0;
}

输出为:

在这里插入图片描述

可以看出,此时根本没有调用与右值匹配的构造函数。

而如果我们在外部实现重载=,这个函数是友元函数,它并不属于类。

当程序执行到a=20,类中若有匹配的构造函数,且外部友元函数也匹配,这时候就会出现二义性。无法判断应该调用哪一个函数。

另外,对于[]举例说明:

假设我们采用采用友元函数实现,并如下设置形参顺序:

char operator[](int idx, mys& Mys)

那么我们显然调用时要写成下面这样的语句:

char temp = 1[Mys];

这显然是不合适的,因此 C + + C++ C++规定其重载只能用成员函数实现。
  ~  

E g 5 : Eg5: Eg5:实现自定义myint类型到int类型的转换。

class myint
{
	int x;
public:
	myint(int x) 
	{
		this->x = x; 
		cout << "myint constructor" << endl;
	}

	//对象强制转换为一般类型
	operator int()
	{
		return x;
	}
};

int main()
{
	myint m(9);
	cout << (int)m << endl;
}

(3)无法重载的运算符
运算符含义
:成员运算符
.*成员指针运算符
::作用域解析运算符
?::三目运算符
sizeof求字节运算符
const_cast强制类型转换运算符
  • 7
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

指针常量

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值