c++运算符重载

运算符重载:运算符重载只是一种”语法上的方便”,也就是它本质只是另一种函数调用的方式

运算符重载和其他函数一样也是一个函数,当编译器遇到适当的模式时,就会调用这个函数

定义重载的运算符就像定义函数,只是该函数的名字是operator@,这里的@代表了被重载的运算符。函数的参数中参数个数取决于两个因素

1运算符是一元(一个参数)的还是二元(两个参数);

2运算符被定义为全局函数(对于一元是一个参数,对于二元是两个参数)还是成员函数(对于一元没有参数,对于二元是一个参数-此时该类的对象用作左耳参数)

代码如下:

#include<iostream>
using namespace std;
class people
{
	//重载<<运算符
	friend ostream& operator<<(ostream& os, people& peo)
	{
		os << peo.age << endl;
		return os;
	}

public:
	people()
	{
		age = 10;
	}
	people(int age)
	{
		this->age = age;
	}

	people(const people& peo)
	{
		cout << "拷贝构造" << endl;
		age = peo.age;
	}
	//+运算符是两元运算符,在成员函数中重载只需要一元参数,类中本身对象也是一个参数
	people operator+(people& peo)
	{
		people tem(peo.age + this->age);
		return tem;
	}

public:
	int age;

};

#if 0
//在全局函数重载要两元参数
people operator+(people& peo1,people& peo2)
{
	people tem(peo1.age+peo2.age);
	return tem;
}
#endif
void test2()
{
	people p1;
	people p2;
	people p3 = p1 + p2;//p3=p1.operator+(p2)
	cout << p3 << endl;
}


int main()
{
	//test();
	test2();
	system("pause");
	return 0;
}
运算符重载成员函数和全局函数结果都一样




前置++和后置++的本质就是运算符重载

//重载前置++和后置++
class person
{
	//重载<<运算符
	friend ostream& operator<<(ostream& os, person& per)
	{
		os << per.age << endl;
		return os;
	}
public:
	person()
	{
		age = 10;
	}
	//前置++
	person& operator++()
	{
		age++;
		return *this;
	}
	//后置++
	person operator++(int)
	{
		person p2;
		p2.age = this->age;
		age++;
		return p2;
	}
public:
	int age;

};

void test()
{
	person per;
	cout << "persn后置++等于" << per++ << endl;//返回的是临时对象,临时对象保存的是原来的值

	cout << "persn前置++等于" << ++per << endl;//前面前置++对象加了1,在加上1就是2

}
int main()
{
	test();
	//test2();
	system("pause");
	return 0;
}

结果:



注意:从上面可以看出,能用前置++,就用前置++,因为前置++不用创建临时对象,效率高,除非需要后置++的原来的值


重载赋值运算符

赋值运算符重载很容易和拷贝构造函数混淆,在对象还没有初始化构造的时候,=调用的是拷贝构造函数,如果对象初始化后,=调用的是重载赋值运算符函数,默认赋值函数是进行简单的值拷贝(浅拷贝)

#include<iostream>
using namespace std;
class student
{
public:
	student()
	{
		this->id = 10;
	}
	student(int id)
	{
		this->id = id;
	}
	student(const student& st)
	{
		cout << "拷贝构造" << endl;
		this->id = st.id;
	}


public:
	int id;
};


void tsteS()
{
	student Stu1(100);
	student Stu2 = Stu1;//调用拷贝构造函数,Stu2没有初始化构造
	cout << "Stu2="<<Stu2.id << endl;
	cout << "----------------------" << endl;

	
	student Stu3;
	Stu3 = Stu1;//这个不调用拷贝构造,因为Stu3已经调用默认构造初始化了,所以调用的是默认赋值运算功能
				//从结果可以看出默认赋值功能是进行简单的值拷贝,如果有指针的话就得重载赋值运算符的功能了
	cout << "Stu3="<<Stu3.id << endl;

}
int main()
{
	tsteS();
	system("pause");
	return 0;
}

结果如图:Stu3=Stu1并没有调用拷贝构造



赋值运算符的深拷贝

#define _CRT_SECURE_NO_WARNINGS
#include<iostream>
using namespace std;
//如果类的内部有指针,并且指针指向堆上的内存。
//默认把析构函数 赋值函数 拷贝构造函数都写上。
class Point
{
public:
	Point(const char* name)
	{
		this->name = new char[strlen(name) + 1];
		strcpy(this->name, name);
	}

	Point(const Point& p)
	{
		
		this->name = new char[strlen(p.name) + 1];
		strcpy(this->name, name);
	}

	//一定要返回引用类型,不然实现连续赋值的时候产生新的对象,赋值错误
	Point& operator=(const Point& p)
	{
		
		//这个时候当前对象已经创建了,name已经指向了堆内存,直接赋值的话会导致堆内存没有及时释放
		//释放原来的内存
		if (name != NULL)
		{
			delete[] name;
			this->name = NULL;
		}
		//开辟新的内存
		this->name = new char[strlen(p.name) + 1];
		strcpy(this->name, p.name);
		return *this;
	}

	~Point()
	{
		if (name != NULL)
		{
			delete[] name;
			this->name = NULL;
		}
		
		
	}
public:
	char* name;
};
int main()
{
	Point p1("make");
	Point p2("peter");
	Point p3("joke");
	//(p3= p2) = p1;//如果不是返回值引用的话,p3就是p2的值,p3=p2产生新的对象,p1就给新的对象赋值了,没有赋值给p3,新的对象调用拷贝构造
	p3 = p2 = p1;//如果不是引用的话,p2=p1产生新的对象,新的对象调用默认构造,赋值给p3就会出现值未知乱码
	cout << p1.name << endl;
	cout << p2.name << endl;
	cout << p3.name << endl;
	system("pause");
	return 0;
}
如果赋值运算符函数返回值不是引用的话结果如下:



如果赋值运算符函数返回值是引用的话结果如下:



注意:除了赋值号(=)外,基类中被重载的操作符都将被派生类继承。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值