运算符重载的目的及应用场景

运算符重载的目的是让我们可以对自己编写的类实现 + – * / 等运算操作,更多的比如>> <<  new delete 等运算符都是可以重载的,将这些运算符重载后我们就可以对类中的数据成员实现我们需要的运算了。

比如正常情况下,加号运算符(+)在给普通的字面值常量做运算时,可以计算出两个数的和(1+2=3),而如果是两个类相加会得出什么结果呢?思考这个问题之前我们就要先考虑,类中都有什么数据,如果是一组int类型的数据,我们希望两个类中所有对应的int数据相加得出结果到另外一个类中。如果是一组字符串数据,则我们希望让两个类中的两组字符串连接起来,将连接后的结果放到另外一个类中。这便是运算符重载的应用场景,但绝不只这些。下面一幅图表示了运算符重载的示例:

存放两个int类型数据的类相加的示例图:

2015-05-16_195143

存放两个string类型数据的类相加的示例图:

2015-05-16_195815

了解清楚了作用,我们做一个小的例子来体验一下运算符重载的强大。运算符重载的语法如下:

函数类型 operator 运算符名称(形参表列)
{
     重载实体;
}
#include <iostream>

using namespace std;

class Complex
{
public:
	Complex(int x, int y)
		:_x(x), _y(y){}

	// 重载+号运算符
	Complex operator+(Complex& another)
	{
		// this此时是s1,another此时是s2
		return Complex(
			this->_x + another._x, 
			this->_y + another._y);
	}
	// 打印_x和_y的值
	void display()
	{
		cout << "_x = " << _x << endl;
		cout << "_y = " << _y << endl;
	}

private:
	int _x;
	int _y;
};

int main(int argc, char* argv[])
{
	Complex c1(10, 20);
	Complex c2(15, 25);
	// 构建一个新对象,其内容由c1 + c2得出
	// 此时c1 + c2就会调用我们编写的operator+函数
	// 此句等同于 c3 = c1.operator+(c2)
	Complex c3 = c1 + c2;

	return 0;
}

以上是一个简单的运算符重载的例子,本文主要是让大家了解运算符重载的目的和一些简单应用,更多的应用案例将在后面的文章介绍,下面我们介绍一下运算符重载的复杂规则。(摘自:传智播客 教师课件

【重载规则】

(1)C++不允许用户自己定义新的运算符,只能对已有的 C++运算符进行重载。例如,有人觉得 BASIC 中用“* *”作为幂运算符很方便,也想在 C++中将“* *”定义为幂运算符,用“3* *5”表示 35,这是不行的。

(2)C++允许重载的运算符
C++中绝大部分运算符都是可以被重载的。

2015-05-16_201649

不能重载的运算符只有 5个:

.       (成员访问运算符)
.*      (成员指针访问运算符)
::      (域运算符)
sizeof  (长度运算符)
?:      (条件运算符)

前两个运算符不能重载是为了保证访问成员的功能不能被改变,域运算符合 sizeof 运算符的运算对象是类型而不是变量或一般表达式,不具备重载的特征。

(3)重载不能改变运算符运算对象(即操作数)的个数。如,关系运算符“>”和“<”等是双目运算符,重载后仍为双目运算符,需要两个参数。运算符”+“,”-“,”*“,”&“等既可以作为单目运算符,也可以作为双目运算符,可以分别将它们重载为单目运算符或双目运算符。

(4)重载不能改变运算符的优先级别。例如”*“和”/“优先级高于”+“和”-“,不论怎样进行重载,各运算符之间的优先级不会改变。有时在程序中希望改变某运算符的优先级,也只能使用加括号的方法强制改变重载运算符的运算顺序。

(5)重载不能改变运算符的结合性。如,复制运算符”=“是右结合性(自右至左),重载后仍为右结合性。

(6)重载运算符的函数不能有默认的参数否则就改变了运算符参数的个数,与前面第(3)点矛盾。

(7)重载的运算符必须和用户定义的自定义类型的对象一起使用,其参数至少应有一个是类对象(或类对象的引用)。

也就是说,参数不能全部是 C++的标准类型,以防止用户修改用于标准类型数据成员的运算符的性质,如下面这样是不对的:
代码如下:

int operator + (int a,int b)
{
     return(a-b);
}

原来运算符+的作用是对两个数相加,现在企图通过重载使它的作用改为两个数相减。如果允许这样重载的话,如果有表达式 4+3,它的结果是 7 还是 1 呢?显然,这是绝对要禁止的。

(8)用于类对象的运算符一般必须重载,但有两个例外,运算符”=“和运算符”&“不必用户重载。复制运算符”=“可以用于每一个类对象,可以用它在同类对象之间相互赋值。因为系统已为每一个新声明的类重载了一个赋值运算符, 它的作用是逐个复制类中的数据成员地址运算符&也不必重载,它能返回类对象在内存中的起始地址。

(9)应当使重载运算符的功能类似于该运算符作用于标准类型数据时候时所实现的功能。例如,我们会去重载”+“以实现对象的相加,而不会去重载”+“以实现对象相减的功能,因为这样不符合我们对”+“原来的认知。

(10)运算符重载函数可以是类的成员函数,也可以是类的友元函数,还可以是既非类的成员函数也不是友元函数的普通函数。

1 comment

评论