运算符重载

在这里插入图片描述

+ 加号运算符重载

class Person {
public:
 	int m_A;
 	int m_A;
 };
 Person p1;
 p1.m_A = 10;
 p1.m_B = 20;
 
 Person p2;
 p2.m_A = 10;
 p2.m_B = 20;
 
 Person p3 = p1 + p2;//要重载这个+号,才能正确执行

下面是通过成员函数重载+号,要写在Person类里面,这里为了清晰一点所以才抽出来写

Person operator+ (Person &p) {
	Person tmp;
	tmp.m_A = this->m_A + p.m_A;
	tmp.m_B = this->m_B + p.m_B;
	return tmp;
}
Person p3 = p1.operator+(p2);
简化为:
Person p3 = p1 + p2;

下面是通过全局函数重载+号,写在类外

Person operator+ (Person &p1, Person &p2) {
	Person tmp;
	tmp.m_A = p1.m_A + p2.m_A;
	tmp.m_B = p1.m_B + p2.m_B;
	return tmp;
}
Person p3 = operator+(p1, p2);
简化为:
Person p3 = p1 + p2;	

利用函数重载,改变这个加号的意义(继续重载“+”)

函数重载的版本,(全局函数重载“+”)
Person operator+ (Person &p1, int num) {
	Person tmp;
	tmp.m_A = p1.m_A + num;
	tmp.m_B = p1.m_B + num;
	return tmp;
}
Person p3 = operator+ (p1, 10);//实质,下面是简化
Person p4 = p1 + 10;//成功执行,并且p1的m_A和m_B都加上了10,然后拷贝给p3

ps:对于内置的数据类型的表达式的运算符是不能修改的(int double float等 都是内置数据类型)
刚才上面的例子的数据类型是自定义的Person数据类型,只有这种自定义的数据类型可以重载运算符。





“<<” 左移运算符重载(只能用全局函数去重载)

作用:可以输出自定义数据类型;同样注意是只能对自定义数据类型的运算进行重载。

用上面重载加号的类 实现重载<<的例子
ps:一般不会利用成员函数重载左移运算符,因为无法实现cout在左侧
void operator<<(cout) {}    ————> p.operator<<(cout); 简化版本: p << cout ;  反了

只能用全局函数重载左移运算符
void operator<<(const ostream &cout, Person &p) {
	cout << "m_A = " << p.m_A << "   m_B = " << p.m_B;
	链式编程思想,此时如果在外部直接使用重载后的版本进行输出p,那么这个语句末尾不能加<<endl; 否则会报错。因为前一个<<被重载成返回值是void,无法执行后面的换行。
}

ostream& operator<<(const ostream &cout, Person &p) {
	cout << "m_A = " << p.m_A << "   m_B = " << p.m_B << endl;
	return cout;
	这里才可以在外部使用重载版本后无限追加输出<<  
}
	
//本质
operator<<(cout,p)  ——>简化为: cout << p; 
ps: 可以利用友元实现输出自定义的数据类型。



++ 递增运算符重载

重载递增运算符

自定义整型
class MyInteger (
friend ostream& operator<<(ostream &cout, MyInteger myint);
	public:
		MyInteger():m_Num(0){}
	private:
		int m_Num;

	public:
	//前置递增重载,返回值一定要用引用,因为是要对同一个变量进行递增,引用是别名,还是同一个变量,否则则是创建了新的对象,对新的对象进行递增,则不能进行连续的递增操作 ++(++m_Num)	
	MyInteger& operator++() {
		m_Num++;
		return *this;
	}
	
	//后置递增重载,用int代表占位参数,区分前置和后置的重载版本...注意后置递增重载需要返回一个值,否则则是返回了局部对象的引用。因为返回的tmp是作为局部对象来做临时记录的,会在函数执行完之后会被释放掉。
	MyInteger operator++(int) {
		//先返回结果,后递增,这是后置递增的特点,但是如果先返回就直接退出了,所以先记录,再递增,后返回前面记录的值
		MyInteger tmp = *this;
		m_Num++;
		return tmp;
	}	
};
重载左移运算符
ostream& operator<<(ostream &cout, MyInteger myint) {
	cout << myint.m_Num;
	return cout;
}

= 赋值运算符重载

C++编译器至少给一个类添加4个函数
1.默认构造函数
2.默认析构函数
3.默认拷贝构造函数,对属性进行值拷贝
4.赋值运算符 operator= 对属性进行值拷贝(operator= 是一个函数名)

系统默认给类提供的赋值运算符写法是简单的值拷贝,导致如果类中有指向堆区的指针,就有可能出现深浅拷贝的问题,所以要重载 = 运算符。并且如果想要链式编程的话,注意返回对象本体。

class Person {
public:
	Person(int age) {
		this->m_age = new int(age);
	}
	
	~Person() {
		if (this->m_age != NULL) {
			delete this->m_age;
			this->m_age = NULL;
		}
	}
	
	//重载赋值运算符,解决默认的赋值运算符的赋值浅拷贝带来的重复释放内存的问题
	Person& operator=(const Person &p) {
		//this->m_age = p.m_age;这是编译器默认的
		 
		//应该先判断是否有属性在堆区,有的话先释放,再作拷贝
		if (this->m_age != NULL) {
			delete this->m_age;
			this->m_age = NULL;
		}
		
		//深拷贝
		this->m_age = new int(*p.m_age);

		//为了可以链式编程,要返回对象本体
		return *this;
	}	

private:
	int *m_age;
};

int main() {
	Person p1(10);
	Person p2(20);
	p2 = p1; //如果没有重载=,则是默认的赋值浅拷贝,会导致内存重复释放
	Person p3 = p2 = p1; //为了可以链式编程,要返回对象本体
	return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值