C++操作符重载学习与使用-算数运算符、赋值、自增、输入输出操作符

C++操作符重载学习与使用-算数运算符、赋值、自增、输入输出操作符

操作符重载概念

class Complex
{
	int real;
	int img;
public:
	Complex():real(0),img(0){};
	Complex(int r,int i):real(r),img(i){};
}

Complex c1;
Complex c2 = Complex(1,2);

c1 + c2;
// 尝试进行 C1 + C2 的操作

程序运行报错,说明对于 c1c2 来说,是无法直接进行算术运算符操作的,可以重定义或重载大部分 C++ 内置的运算符,这样就能使用自定义类型的运算符进行操作,这里将进行算术运算符的重载。

首先来看一个常规操作

Complex addNumber(Complex &p1)
{
	Complex p3;
	p3.real = this->real + p1.real;
	p3.img = this->img + p1.img;
	return p3;
}

Complex c3 = c1.addNumber(c2);

这种方式看起来可以实现,但是每次都需要调用函数去计算,如何进行化简呢?

Complex operator+(Complex &p1)
{
	Complex p3;
	p3.real = this->real + p1.real;
	p3.img = this->img + p1.img;
	return p3;
}

Complex c3 = c1 + c2;
// 等价于 Complex c3 = c1.operator+(c2);

以上就是算数运算符重载的实现方式,这种方式叫做成员函数重载,此外,还可以定义友元方式的重载。
首先在类中声明友元函数

friend Complex operator+(Complex &p1, Complex &p2);

由于友元是没有 this 指针的,所以要标明形参。

Complex operator+(Complex &p1, Complex &p2)
{
	Complex p3;
	p3.real = p1.real + p2.real;
	p3.img = p1.img + p2.img;
	return p3;
}

友元调用形式为:

Complex c3 = c1 + c2;
// 等价于 Complex c3 = operator+(c1, c2);

注意:对于不是一定需要 this 指针的一般定义为友元重载,会让调用更加方便。为什么这么说呢,看个例子,如果是 int k = a + b; 的形式,使用成员函数重载是没问题的,a是一个对象可以调用 this 指针,但是如果是 int k = 1 + b;,那么对成员是不可行的,而友元可行。

赋值操作符重载

Complex c3 = c2;  // 调用拷贝构造函数

Complex c3;
c3 = c2;  // 不会调用拷贝构造函数
// 这是因为编译器会默认合成一个赋值运算符重载函数

这里的赋值运算符重载函数必须要定义为成员函数,因为它一定需要用到 this 指针。

Complex &operator=(const Complex &c)
{
	if(this != &c)  // 因为 this 是一个非 const,而c是const,所以不能写成 *this != c
	{	
		real = c.real;
		img = c.img;
	}
	return *this;
}

自增运算符重载

自增运算符的重载包括两种,一种是前置++,一种是后置++

Complex &operator++()
{	// 前置++
	real++;
	img++;
	return *this;
}

Complex c3;
++c3;
Complex operator++(int i)  // 这里的 int i 仅仅用于区别重载
{	// 后置++
	real++;
	img++;
	return *this;
}

Complex c3;
c3++;

前置++版本返回值为引用,其表示进行++之后的对象;而后置++表示++之前的值的对象。这样来看,其实上面后置++的写法是有问题的,既然后置++表示++之前的值的对象,那么应该这样写:

Complex operator++(int i)   // 这里的 int i 仅仅用于区别重载
{	// 后置++
	Complex tmp = *this;
	real++;
	img++;
	return tmp;
}

Complex c3;
c3++;

输入输出操作符重载

1、输出操作符重载,不能定义为成员函数(因为如果是成员函数,左侧的运算对象必须是本类的对象);
2、可以定义为友元,以便访问私有域;
3、需要 out 内容。

friend void operator<<(ostream &out, const Complex &c);
void operator<<(ostream &out, const Complex &c)   // 这里需要输出对象out
{
	cout << c.real << "+" << c.img <<endl;
}

采用上述方法时,没有办法连续输出,因为前部分返回类型 void,不能再继续被使用。为了能够进行连续输出,需要将返回值定义为 ostream 的引用。

ostream & operator<<(ostream &out, const Complex &c)
{
	cout << c.real << "+" << c.img;  //尽量不要在函数中添加换行符
	return out;
}

cout << c1 << c2 << c3;

ostreamoutput stream的简称,即输出流,在C++中用来输出。一个典型的输出流对象就是在C++中标准输出流cout。在C++中,很少自定义ostream的对象,更多的是直接使用coutostream这个类型,往往出现在<<操作重载中,作为某个类的友元函数出现。

类似的,对于输入操作符的重载,只需要修改以下细节:

iostream & operator>>(istream &in, Complex &c)
{
	in >> c.real;
	in >> c.img;
	return in;
}

cin >> c3;

因为需要修改值,所以不能使用 const 修饰 c

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值