运算符重载

C++可以通过运算符重载来完成用户定义类型的运算。具体语法就是把函数名换成operator@,其中@代表特定的运算符。

#include<iostream>
#include<cstdio>
using namespace std;

class NODE
{
private:
	int x, y;

public:
	NODE(int _x = 0, int _y = 0)
	{
		x = _x;
		y = _y;
	}

	NODE operator+(NODE &a) const;  //对+重载
	 
	NODE operator-(NODE &a) const;  //对-重载
};

NODE NODE::operator+(NODE &a) const
{
	NODE t;
	t.x = this->x + a.x;
	t.y = this->y + a.y;
	return t;
}

NODE NODE::operator-(NODE &a) const
{
	NODE t;
	t.x = this->x - a.x;
	t.y = this->y - a.y;
	return t;
}

int main()
{
	NODE a(1, 1), b(2, 2);
	NODE add, sub, mul;
	add = a + b;  //相当于调用a.operator+(b)
	sub = a - b;  //相当于调用a.operator-(b)

	return 0;
}

现在对*进行重载,让类和一个int类型的数据相乘。

NODE operator*(int x);  //函数原型

NODE NODE::operator*(int x)  //函数定义
{
	NODE t;
	t.x = this->x*x;
	t.y = this->y*x;
	return t;
}
当遇到a*b时(a是NODE类型,b是int类型),将转换成a.operator*(b)来调用。

但如果遇到b*a呢,会转换成b.operator*(a),但实际上并没有这个函数原型,因此会报错。

C++提供友元函数来解决这个问题

友元函数
通过让函数成为类的友元,可以赋予该函数与类的成员函数相同的访问权限。即类的友元函数可以方位类的私有成员。因此,友元函数不是类的成员函数,它是一般函数,但是它能访问类的私有成员。
创建友元函数的第一步是在类中声明它的原型,代表它是该类的友元函数,需要关键字friend。
第二步就是编写函数定义,在类外编写。因为它不是成员函数,因此不需要加类名来限定。
#include<iostream>
#include<cstdio>
using namespace std;

class NODE
{
private:
	int x, y;

public:
	NODE(int _x = 0, int _y = 0)
	{
		x = _x;
		y = _y;
	}

	NODE operator+(NODE &a) const;  //对+重载
	 
	NODE operator-(NODE &a) const;  //对-重载

	NODE operator*(int x);

	friend NODE operator*(int x, NODE &a);
};

NODE operator*(int x, NODE &a)
{
	NODE t;  //这4行完全可以换成 return a*x;  相当于调用a.operator(x)
	t.x = x*a.x;
	t.y = x*a.y;
	return t;
}

NODE NODE::operator*(int x)
{
	NODE t;
	t.x = this->x*x;
	t.y = this->y*x;
	return t;
}

NODE NODE::operator+(NODE &a) const
{
	NODE t;
	t.x = this->x + a.x;
	t.y = this->y + a.y;
	return t;
}

NODE NODE::operator-(NODE &a) const
{
	NODE t;
	t.x = this->x - a.x;
	t.y = this->y - a.y;
	return t;
}


int main()
{
	NODE a(1, 1), b(2, 2);
	NODE add, sub, mul;
	add = a + b;  //这里调用的是a.operator+(b)
	sub = a - b;  //这里调用的是a.operator-(b)
	mul = a * 1;  //这里调用的是a.operator(1)
	mul = 1 * a;  //这里调用的operator*(1,a)

	return 0;
}
另外还可以重载运算符<<,来输出用户定义的类。即cout<<a。其中,a是某个类的对象。
cout是ostream对象,能识别所有C++基本类型。因为对于基本类型,ostream类声明中都包含了相应的重载的operator<<()的定义。我们也可以重载<<来输出自己定义的类。
因为cout<<a。可以看出是双目运算符,cout作为第一个参数,a作为第二个参数。因此不能通过类的成员函数进行重载,因为那样子会默认类对象是第一个参数(这和上面1*a是一样道理)。因此只能作为友元函数进行重载。
第一个版本:
#include<iostream>
#include<cstdio>
using namespace std;

class NODE
{
private:
	int x, y;

public:
	NODE(int _x = 0, int _y = 0)
	{
		x = _x;
		y = _y;
	}

	friend void operator<<(ostream &os, NODE &a);
};

void operator<<(ostream &os, NODE &a)
{
	os << a.x << " " << a.y << endl;
}

int main()
{
	NODE t;
	cout << t;

	return 0;

}

但是还有一个问题,这个版本无法处理类似cout<<a<<b;的情况。
先看常规的cin>>x>>y;这里x和y都是基本类型。C++从左至右输出语句,所以它等价于 (cout<<x)<<y; 因为在ostream类中的operator<<重载,返回的依然是ostream类的引用,且该引用就是传进去的参数cout。因此cout<<x最终将返回cout,该cout再用来输出y。
因此要修改成如下
#include<iostream>
#include<cstdio>
using namespace std;

class NODE
{
private:
	int x, y;

public:
	NODE(int _x = 0, int _y = 0)
	{
		x = _x;
		y = _y;
	}

	friend ostream& operator<<(ostream &os, NODE &a);
};

ostream& operator<<(ostream &os, NODE &a)
{
	os << a.x << " " << a.y << endl;
	return os;
}

int main()
{
	NODE t, a(1, 1);
	cout << t << a;

	return 0;

}

另外,ofstream对象可以用于输出写入到文件,通过继承,ofstream可以使用ostream的方法。类继承属性让ostream引用可以指向ostream对象和ofstream对象。因此还可以通过该重载来将输出写入文件
	ofstream fout;
	fout.open("a.txt");
	fout << t;  //将调用operator<<(fout,t);


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值