【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
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

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
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
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;
}

输出为:

【C++】运算符重载_第1张图片

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

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

#include
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;
}

输出为:

【C++】运算符重载_第2张图片

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

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

当程序执行到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 强制类型转换运算符

你可能感兴趣的:(C++,c++,开发语言)