关于算术运算符重载整合学习笔记

#include<iostream>
#include<string>
using namespace std;
class Person
{
	friend void test();
	friend Person& operator++(Person& p);
	friend ostream& operator<<(ostream& cout, Person a);//涉及到后置++
	friend Person operator+(Person& a, Person& b);
public:
	void operator()(int number)
	{
		cout << number<<endl;
	}
	void show()
	{
		cout << score;
	}
	Person(){}
	Person(int number)
	{
		score = number;
	}
	bool operator==(Person& a)
	{
		if (this->score == a.score)return true;
		return false;
	}
	bool operator!=(Person& a)
	{
		if (this->score != a.score)return true;
		return false;
	}
	/*Person& operator+(Person& a)//非链式调用返回自身;
	{
		this->score += a.score;
		return *this;
	}*/
	Person operator++(int)
	{
		Person temp = *this;
		this->score++;
		return temp;
	}
private:
	int score;
};
void test()
{
	Person huang(5), chao(6);
	if (huang == chao)cout << "the score in op are the same";
	else cout << "no";
}
Person operator+(Person& a, Person& b)//实现加法运算符重载可以允许链式调用;
{
	Person temp;
	temp = a.score + b.score;
	return temp;
}ostream& operator<<(ostream& cout, Person a)
{
	cout << a.score;
	return cout;//可以实现类似链式调用可以输出目标后继续输出endl;
}
Person& operator++(Person& p)
{
	p.score++;
	return p;
}
int main()
{
	//test();
	Person xiao(5), da(6);
	if (xiao != da)cout << "yes" << endl;
	xiao=xiao + da;
	cout << xiao<<endl;
	++xiao;
	cout << xiao<<endl;
	cout << xiao++<<endl;//实现后置++
	cout << xiao<<endl;
	Person ming(3);
	ming(2);//此时为调用函数非启动构造函数;
	ming.show();
	return 0;
}

首先先构建一个Person类包含构造函数无参和有参Person,创建对象xiao,da利用5,6对两对象进行初始
化,由主函数的运行过程可以知道下一步是判断xiao和da两对象中score元素是否相同这里是运用了布尔类型来定义函数的返回类型,定义成员函数是因为设计该重载函数时调用了this指针,由于this指针只能
用于非静态成员函数内部,在重载!=中判断传入的对象和this指针所指向的对象中的score是否相同来返
回不同的布尔类型,由于两对象初始的score值并不相同所以输出yes;
进行第二个操作实现对象的直接相加来实现对象元素的相加需要调用重载运算符号+,可以使用被注释的部
分重载+:

/*Person& operator+(Person& a)//非链式调用返回自身;
	{
		this->score += a.score;
		return *this;
	}*/

该重载返回的类型是本身的拷贝,由于设计使用了this指针所以定义在类中,该重载不可以定义多个参数
也不能进行类似xiao=xiao+da+xiao的链式计算(这部分原因不太了解仅在VS2019上由于编译报错而舍弃
具体原因还有待发现),而将operator+重载类型更改为Person返回的是一个临时的一个对象就可以在不
用this且可以实现定义成全局函数不用写在类中简洁美观,允许传入多个值:

Person operator+(Person& a, Person& b)//实现加法运算符重载可以允许链式调用;
{
	Person temp;
	temp = a.score + b.score;
	return temp;
}

由于score类型是私有数据所以得将该重载添加友元属性,就可以实现对象相加使得成员数据相加。
进而往下就是通过cout<<xiao直接输出xiao中的成员数据由于利用成员函数重载左移运算符无法满足
cout在左侧的习惯,一般利用全局函数来实现左移运算符,神奇的地方来了,在VS2019中通过右击cout来
查看cout的定义来获取ostream类用于参加左移运算符的重载:

void operator<<(ostream& cout, Person &a)
{
	cout << a.score;
}

这样可以实现对对象的内容的输出,由于数据私有型仍然需要添加友元属性,但是这玩意它在输出对象数据后不能再输出endl,这是由于重载的返回值是void在输出完对象后就形成了void<<endl;这就没办法去执行输出了也不能实现链式的调用,那就可以想到返回的东西也是cout,这部分内容是真的神奇,由于cout
估计是ostream的函数所以需要将void更改为ostream&返回一个cout本身,void的空返回是肯定要改的,
由于要实现<<endl的输出不难想到要返回cout,难的是将类型定义成ostream&:

ostream& operator<<(ostream& cout, Person a)
{
	cout << a.score;
	return cout;//可以实现类似链式调用可以输出目标后继续输出endl;
}

接下来就要进行后置++,前置++的重载,后置++时调用了this指针就定义在类中了,由于要与前置区别(这
部分涉及到重载函数的区分,参数据类型,参数名,函数的作用域,不能用函数的返回类型区分重载函数,
就需要使用int来进行占位,由于后置++中必须返回临时对象,此时重载左移运算符的第二个参数必须是使用值而非引用值,尽管在第一次不改变第二参数的类型也可以正常输出但这是编译器的优化进行第二次运行
就会导致崩溃甚至有的编译器连编译都不给通过,具体代码如下:

Person operator++(int)
	{
		Person temp = *this;
		this->score++;
		return temp;
	}

这里是因为后置的作用如果直接返回temp就会出现根本没有对成员数据进行加法操作,所以一开始就要
用到this指针来浅拷贝一个对象让它中的数据不变而目标的成员数据已经改变。
重载前置运算符输出就没有对ostream重载左移运算符的要求:

Person& operator++(Person& p)
{
	p.score++;
	return p;
}

可以进行赋值运算符的重载实现Xiao=da的直接操作,问题是这部分涉及到浅拷贝与深拷贝的问题,若不
进行深拷贝又用析构函数对对象在进行堆区内存释放时会造成释放一个对象后还要对已经被释放的区域进行二次释放,访问权限非法造成程序崩溃,这是由于浅拷贝使得两对象new在堆区使用相同的内存所造成的!
这部分内容掌握得不是太清楚等清楚了再补上,下面进行仿函数重载():

void operator()(int number)
	{
		cout << number << endl;
	}
int main(){
Person ming(3);
ming(2);//此时为调用函数非启动构造函数;
ming.show();

重载函数如上例会引起一定的误解,至少我自己是这么理解的。
此时就会发现如果未在定义对象时调用构造函数,后续用ming(2),再使用show()函数就会发现本该调用构造函数对ming中元素进行赋值却没有输出,输出了个随机数字,这就是一定的误解不太了解这部分的机制,
直接启动operator函数对输入的2进行操作跳过了构造函数使得直接定义对象时输入数据来添加成员数据
还有的重载赋值运算符估计得明天肝,本文内容粗糙,若有错误请指出。

猜你喜欢

转载自www.cnblogs.com/pekkasuper/p/12601898.html