C++中运算符重载【详细讲解】

1、运算符重载的目的

通过运算符重载实现使用同一个运算符可以完成不同的运算功能。类比着函数重载来学习,运算符重载也是在编译阶段完成的。

运算符重载------就是对现有的运算符进行重新定义,赋予其另外一种能力,为了操作不同的数据类型【注意:是重载,不影响运算符原来的功能】

2、运算符重载相关规定

1)运算符重载使用operator关键字;
2)不能改变运算符的优先级;(比如:乘除的优先级高于加减)
3)不能改变原运算符的结合性;(左结合或者右结合)
4)默认参数不能和运算符重载一起使用;
5)不能改变原有运算符的操作数的个数;(单目运算,双目运算或者三目运算)
6)不能改变运算符的性质;(比如:在重载时,不能将对“+”运算符重载为“-”)
7)可以用于用户定义的类对象或者用户定义的类对象与内置成员函数的组合;
8)不能发生重载的运算符。(如下表所示:)

不能发生重载的运算符如下:

成员访问.
域运算符::
计算所占内存sizeof
三目运算符: ?
预处理#
取值运算符*

 只能重载为类内成员函数的运算符如下:(原因:运算符重载为类内成员函数一个至关重要的特点:【类的this指针会被绑定到运算符左侧的运算对象】,也就是说以下运算符的左操作数必须是该类类型的参数)

赋值=
下标[ ]
调用( )
成员访问->

3、运算符重载实现

运算符重载通过【函数】实现。

运算符重载函数主要的三种形式:1)重载为类的成员函数;2)重载为类的友元函数【为了解决普通函数权限不够的问题】;3)普通函数。

4、双目运算符重载(以“+”、“>”、“=”、“<<”(提取)、“>>”(输入)等为例)

双目运算符重载【在类里面实现只能具有一个参数】,隐含的第一个参数是【this指针】【类外进行重载可以有两个参数】

1)算数运算符:“+”的重载

(1)重载为类的成员函数

#include <iostream>

using namespace std;

class MyOperator {
public:
	//构造函数(用来初始化成员属性)
	MyOperator(int data) :Data(data)
	{

	}
	//类型运算符"+"重载【类内重载:默认第一个参数是this】
	MyOperator operator+(MyOperator myoperator)
	{
		MyOperator temp(0);          //创建一个临时对象,在进行函数返回值时候使用
		temp.Data = this->Data + myoperator.Data;
		return temp;
		/*
		注意:该函数中代码不能使用下面的代码代替
		this->Data += myoperator.Data;
		return *this;
		【原因是:运算符在类内重载,默认第一个参数是this指针【指向的是对象本身】,如果使用上述代码会将第一个对象中的值进行修改,不满足加法的本质】
		*/
	}
    
public:
	int Data;
};

int main()
{
	MyOperator a(10);
	MyOperator b(20);
	MyOperator c = a + b;   //调用运算符重载函数来实现两个对象相加【原来"+"号是无法实现两个对象相加的】
	cout << "a.Data的值:" << a.Data << endl;
	cout << "b.Data的值:" << b.Data << endl;
	cout << "c.Data的值:" << c.Data << endl;
	return 0;
}

运行结果:

a.Data的值:10
b.Data的值:20
c.Data的值:30

(2)重载为类的友元函数

#include <iostream>

using namespace std;

class MyOperator {
	friend MyOperator operator+ (MyOperator myopt1, MyOperator myopt2);        //声明成友元函数
public:
	//构造函数(用来初始化成员属性)
	MyOperator(int data) :Data(data)
	{

	}
	//普通成员函数【目的:获取私有成员属性的值】
	int getData()
	{
		return Data;
	}

private:
	int Data;
};
//类外重载"+"函数的定义
MyOperator operator+ (MyOperator myopt1, MyOperator myopt2)     //【注意:这里传递的是值,而不是对象本身,所以不必担心会将原来对象中的值改变】
{
	MyOperator temp(0);
	temp.Data = myopt1.Data + myopt2.Data;
	return temp;
	/*
	注意:该函数中代码可以使用以下代码代替
	myopt1.Data += myopt2.Data;
	return myopt1;
	【原因:传递过来的是值,而不是对象本身】
	*/
}

int main()
{
	MyOperator a(10);
	MyOperator b(20);
	MyOperator c = a + b;   //调用运算符重载函数来实现两个对象相加【原来"+"号是无法实现两个对象相加的】
	cout << "a.Data的值:" << a.getData() << endl;
	cout << "b.Data的值:" << b.getData() << endl;
	cout << "c.Data的值:" << c.getData() << endl;
	return 0;

}

 运行结果:

a.Data的值:10
b.Data的值:20
c.Data的值:30

(3)重载为普通函数

#include <iostream>

using namespace std;

class MyOperator {
public:
	//构造函数(用来初始化成员属性)
	MyOperator(int data) :Data(data)
	{

	}
	//普通成员函数【目的:获取私有成员属性的值】
	int getData()
	{
		return Data;
	}

public:
	int Data;
};
//类外重载"+"函数的定义
MyOperator operator+ (MyOperator myopt1, MyOperator myopt2)     //【注意:这里传递的是值,而不是对象本身,所以不必担心会将原来对象中的值改变】
{
	MyOperator temp(0);
	temp.Data = myopt1.Data + myopt2.Data;
	return temp;
	/*
	注意:该函数中代码可以使用以下代码代替
	myopt1.Data += myopt2.Data;
	return myopt1;
	【原因:传递过来的是值,而不是对象本身】
	*/
}

int main()
{
	MyOperator a(10);
	MyOperator b(20);
	MyOperator c = a + b;   //调用运算符重载函数来实现两个对象相加【原来"+"号是无法实现两个对象相加的】
	cout << "a.Data的值:" << a.getData() << endl;
	cout << "b.Data的值:" << b.getData() << endl;
	cout << "c.Data的值:" << c.getData() << endl;
	return 0;

}

 运行结果:

a.Data的值:10
b.Data的值:20
c.Data的值:30

2)关系运算符:“>”的重载

(1)重载为类成员函数

#include <iostream>

using namespace std;
class MyOperator {
public:
	//构造函数(用于初始化成员属性)
	MyOperator(int data) :Data(data)
	{

	}
	//运算符">"重载为类内函数
	bool operator>(MyOperator a)          //返回值为布尔类型
	{
		if (this->Data > a.Data)
		{
			return true;
		}
		else
		{
			return false;
		}
	}
public:
	int Data;
};

int main()
{
	MyOperator a(10);
	MyOperator b(20);
	if (a > b)              //调用重载运算符,来比较两个对象的大小
	{
		cout << "a > b" << endl;
	}
	else
	{
		cout << "a < b" << endl;
	}
	return 0;
}

运行结果:

a < b

(2)重载为类的友元函数

#include <iostream>

using namespace std;
class MyOperator {
	friend bool operator>(MyOperator a, MyOperator b);          //友元函数的声明   
public:
	//构造函数(用于初始化成员属性)
	MyOperator(int data) :Data(data)
	{

	}
private:
	int Data;
};
// 运算符">"重载为友元函数
bool operator>(MyOperator a, MyOperator b)          //返回值为布尔类型
{
	if (a.Data > b.Data)
	{
		return true;
	}
	else
	{
		return false;
	}
}
int main()
{
	MyOperator a(10);
	MyOperator b(20);
	if (a > b)              //调用重载运算符,来比较两个对象的大小
	{
		cout << "a > b" << endl;
	}
	else
	{
		cout << "a < b" << endl;
	}
	return 0;
}

 运行结果:

a < b

(3)重载为普通函数

#include <iostream>

using namespace std;
class MyOperator {
public:
	//构造函数(用于初始化成员属性)
	MyOperator(int data) :Data(data)
	{

	}
public:
	int Data;
};
// 运算符">"重载为友元函数
bool operator>(MyOperator a, MyOperator b)          //返回值为布尔类型
{
	if (a.Data > b.Data)
	{
		return true;
	}
	else
	{
		return false;
	}
}
int main()
{
	MyOperator a(10);
	MyOperator b(20);
	if (a > b)              //调用重载运算符,来比较两个对象的大小
	{
		cout << "a > b" << endl;
	}
	else
	{
		cout << "a < b" << endl;
	}
	return 0;
}

 运行结果:

a < b

3)赋值运算符:“=”的重载

赋值运算符operator=,对属性进行【值拷贝】编译器会默认提供一个赋值运算符的重载函数

【重点】赋值运算符”=“【只能重载为类的成员函数,不能重载为友元函数或者普通函数】

#include <iostream>

using namespace std;
class MyOperator {
public:
	//构造函数(用于初始化成员属性)
	MyOperator(int data) :Data(data)
	{

	}
	//运算符"="重载为类内函数
	MyOperator operator=(MyOperator a)
	{
		this->Data = a.Data;
		return *this;       //this指针指向的是对象的地址,*this就是这个对象本身
	}
	//普通成员函数(目的:用于获取私有成员属性的值)
	int getData(void)
	{
		return Data;
	}
private:
	int Data;
};
int main()
{
	MyOperator a(10);
	cout << "a.Data当前的值:" << a.getData() << endl;
	cout << "--------------------------------" << endl;
	a = 20;
	cout << "a.Data修改后的值:" << a.getData() << endl;
	return 0;
}

 运行结果:

a.Data当前的值:10
--------------------------------
a.Data修改后的值:20

3)提取运算符:“<<”的重载

(1)为什么要对于“<<”进行重载

在C++中,标准库本身已经对“<<”和“>>”操作符分别进行了重载,使其能够输入输出不同的数据。这些数据均是来自于C++内置的数据(如int、bool、double等)和标准库所包含的类型(如string、complex等)。如果用户自己定义了一种新的数据类型,需要使用输入输出运算符去处理时,就需要进行重载。

(2)如何实现

  • 首先,需要明确一个问题,cout其实是ostream中的类对象,也就是需要将cout看做一个对象。因此,在对“<<”进行重载时,只能重载为普通函数或者友元函数【因为重载为类内函数默认第一个参数是this指针】

  • 其次,直接上程序。程序中有详细注释,可以帮助理解。【代码是重载为普通函数的代码,重载为友元函数只需要稍微改动一下即可】

#include <iostream>

using namespace std;

class MyOperator {
public:
	//构造函数
	MyOperator(int data) :Data(data)
	{

	}
public:
	int Data;
};
//重载为普通函数
ostream& operator<<(ostream& output_c, MyOperator a)//注意这里的第一个参数传入的是引用,将cout的引用传递给output_c
													//这样output_c才能作为标准输出
{
	output_c << a.Data;
	return output_c;                                //注意这里的返回值,返回值类型为ostream&,而不是单纯的ostream
													//如果这里只是单纯ostream的话,返回的是值,会导致后面再次输出a的时候出现错误【简单来说,就是无法实现连续输出,只能一个一个输出】
}

int main()
{
	MyOperator a(10);
	cout << a << endl;;
	return 0;
}

运行结果:

10

结果解释:【程序中的注释结合图像来理解这部分代码】

 4)输入运算符:“>>”的重载

基本内容与提取运算符“<<”的一致,只是存在一点不同。“>>”输入运算符会【改变对象的值】,因此在进行重载时,【需要传入的是对象的引用】

重载为普通成员函数:

#include <iostream>

using namespace std;

class MyOperator {
public:
	//构造函数
	MyOperator(int data) :Data(data)
	{

	}
public:
	int Data;
};
//"<<"重载为普通函数
ostream& operator<<(ostream& output_c, MyOperator a)//注意这里的第一个参数传入的是引用,将cout的引用传递给output_c
													//这样output_c才能作为标准输出
{
	output_c << a.Data;
	return output_c;                                //注意这里的返回值,返回值类型为ostream&,而不是单纯的ostream
													//如果这里只是单纯ostream的话,返回的是值,会导致后面再次输出a的时候出现错误
													//【简单来说,就是无法实现连续输出,只能一个一个输出】
}
//">>"重载为普通函数
istream& operator >>(istream& input_c, MyOperator& a)      //注意这里的第二个参数,传递的是对象的引用而不是对象中的值
{
	input_c >> a.Data;
	return input_c;
}

int main()
{
	MyOperator a(10);   //初始a对象中的Data属性的值为10
	cout << "a中初始Data的值为:" << a << endl;
	cin >> a;
	cout << "a中修改后Data的值为:" <<a << endl;
	return 0;
}

运行结果:

a中初始Data的值为:10
20
a中修改后Data的值为:20

5、单目运算符重载(以“++”为例)

1)递增运算符++

前置++和后置++的区别:

返回类型不同前置++的返回类型是&(引用类型);而后置++返回类型是const(常量类型)。这就表明,前置++返回的是左值,可以被修改;而后置++返回的是右值,不可以被修改
形参不同前置++与后置++的操作符重载函数的函数原型不同。在进行重载时,后置++增加了一个int形参
代码不同前置++代码实现较为简单;而后置++实现较为复杂,因为需要提前拷贝出来一份原来的值
执行顺序不同前置++首先增加变量的值,然后返回新值;后置++首先返回变量当前的值,然后增加变量的值

 2)程序

(1)重载为类成员函数

#include <iostream>

using namespace std;

class MyOperator {
public:
	MyOperator(int data):Data(data)
	{

	}
	//前置++重载为类内函数
	MyOperator &operator++(void)
	{
		this->Data += 1;
		return *this;               //返回的是引用,也就是对象本身,不是值
	}
	//后置++重载为类内函数
	MyOperator operator++(int)      //参数填写一个int是为了满足标准语法要求
	{
		MyOperator temp(0);         //临时对象,做拷贝使用
		temp.Data = this->Data;     //先进行拷贝
		this->Data += 1;            //再实现自增
		return temp;                //最后返回副本的值
	}
public:
	int Data;
};

int main()
{
	MyOperator a(100);
	cout << "前置++后a.Data的值为:" << ++a.Data << endl;
	cout << "后置++后a.Data的值为:" << a++.Data << endl;
	return 0;
}

 运行结果:

前置++后a.Data的值为:101
后置++后a.Data的值为:101

(2)重载为普通函数

#include <iostream>

using namespace std;

class MyOperator {
public:
	MyOperator(int data):Data(data)
	{

	}
public:
	int Data;
};
//前置++重载为普通函数
MyOperator& operator++(MyOperator &a)
{
	a.Data += 1;
	return a;                   //返回的是引用,也就是对象本身,不是值
}
//后置++重载为普通函数
MyOperator operator++(MyOperator &a,int)      //参数填写int是为了满足标准语法要求
{
	MyOperator temp(0);         //临时对象,做拷贝使用
	temp.Data = a.Data;         //先进行拷贝
	a.Data += 1;                //再实现自增
	return temp;                //最后返回副本的值
}
int main()
{
	MyOperator a(100);
	cout << "前置++后a.Data的值为:" << ++a.Data << endl;
	cout << "后置++后a.Data的值为:" << a++.Data << endl;
	return 0;
}

运行结果:

前置++后a.Data的值为:101
后置++后a.Data的值为:101
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值