C++类和对象——运算符重载

运算符重载:对已有的运算符进行重新定义,赋予其另一种功能,以适应不同的数据类型。

加号运算符重载

加号运算符重载:实现两个自定义数据类型的相加操作。

#include<iostream>
using namespace std;
//加号运算符重载
class Person {
public:
	/*1、通过成员函数重载加号
	Person operator+(Person & p) {
		Person temp;
		temp.m_a = this->m_a + p.m_a;
		temp.m_b = this->m_b + p.m_b;
		return temp;
	}*/
	int m_a;
	int m_b;
};
//2、通过全局函数重载加号
Person operator+(Person &p1,Person &p2) {
	Person temp;
	temp.m_a = p1.m_a + p2.m_a;
	temp.m_b = p1.m_b + p2.m_b;
	return temp;
}
//函数重载的版本
//运算符重载也可以发生在函数重载
Person operator+(Person p,int num) {
	Person temp;
	temp.m_a = p.m_a + num;
	temp.m_b = p.m_b + num;
	return temp;
}
void test01(){
	Person p1;
	p1.m_a = 10;
	p1.m_b = 10;
	Person p2;
	p2.m_a = 10;
	p2.m_b = 10;
	//成员函数调用本质
	//Person p3 = p1.operator+(p2);
	//全局函数调用本质 
	//Person p3 = p1.operator+(p1,p2);
	Person p3 = p1 + p2;
	cout <<"p3的值a为" <<p3.m_a << "  p3的值b为" << p3.m_b << endl;
	Person p4 = p1 + 100;
	cout << "p4的值a为" << p4.m_a << "  p4的值b为" << p4.m_b << endl;
}
int main() {
	test01();
	system("pause");
	return 0;
}

左移运算符重载

左移运算符重载:可以输出自定义数据类型。

#include<iostream>
using namespace std;
//重载左移运算符是想直接输出一个对象,重载左移运算符可以配合友元可以实现输出自定义数据类型
class Person {
	friend ostream& operator<<(ostream& cout, Person& p);   //全局函数做友元
public:
	Person(int a,int b) {
		m_a = a;
		m_b = b;
	}
private:
	/*利用成员函数重载左移运算符 p.operator<<(cout) 简化版本p<<cout
	不能利用成员函数重载左移运算符,因为这样无法实现cout在左侧
	void operator<<(cout) {

	}*/
	int m_a;
	int m_b;
};
//只能利用全局函数重载左移运算符
//cout全局只能有一个,所以必须用引用的方式传进来,不能创建出来新的一个
ostream & operator<<(ostream &cout,Person &p) {   //本质是operator<<(cout,Person p) 简化版本cout<<p
	cout <<"输出a"<< p.m_a <<"输出b" <<p.m_b << endl;
	return cout;
}
void test01() {
	Person p(10,10);
	/*p.m_a = 20;
	p.m_b = 10;*/
	cout << p<<endl;   //链式编程思想
}
int main() {
	test01();
	system("pause");
	return 0;
}

递增运算符重载

递增运算符重载:实现对自定义数据类型的递增操作。

#include<iostream>
using namespace std;
//自定义整型类
class Integer {
	friend ostream& operator<<(ostream& cout, Integer myint);   //全局函数做友元
public:
	Integer() {
		m_number = 0;
	}
	//重载前置++运算符 返回引用是为了一直对一个数据进行递增操作
	Integer& operator++() {
		//先进行++运算
		m_number++;
		//再将自身做返回
		return *this;
	}
	//重置后置++运算符 这里的参数int代表占位参数,区分函数重载
	//区分前置后置用占位参数int就可以区分了
	//后置递增一定要返回的是值
	Integer operator++(int) {              //前置递增返回的是引用,后置递增返回的是值!!!!!!!!!!!!!!!!!
		//先记录当前结果
		Integer temp = *this;          //temp是一个局部对象,当前函数执行完temp就被释放掉了,如果引用只能引用一次,再引用第二次就是非法操作
		//再进行递增操作
		m_number++;
		//最后将记录结果作返回
		return temp;

	}
private:
	int m_number;
};
//重载左移运算符
ostream &operator<<(ostream &cout,Integer myint) {
	cout << myint.m_number << endl;
	return cout;
}


void test01() {     //++a操作  前置递增
	Integer myint;
	cout << ++(++myint)<<endl;
	cout << myint << endl;
} 
void test02() {     //a++操作  后置递增
	Integer myint;
	cout << myint++ << endl;
	cout << myint<<endl;
}

int main() {
	test01();
	test02();

	//内置数据类型会一直对同一个数据进行操作,但是++(++myint)相当于加完一次就成为了一个新数据,因此需要引用返回来保证一直对一个数据进行操作
	/*int a = 0;
	cout << a++ << endl;
	cout << a << endl; */
	system("pause");
	return 0;
}

递减运算符重载

递减运算符重载:实现对自定义数据类型的递减操作。

#include<iostream>
using namespace std;
class Myinteger {
	friend ostream& operator<<(ostream& cout, Myinteger myint);//左移运算符函数做友元,访问私有属性

public:
	Myinteger() {
		m_number = 10;
	}
	//重载前置递减运算符
	Myinteger &operator--() {
		//先递减
		m_number--;
		//再返回结果
		return *this;
	}
	//重载后置递增运算符
	Myinteger operator--(int) {         //int做占位参数来区分函数重载
		//先返回当前值
		Myinteger temp = *this;
		//再进行递减操作
		m_number--;
		//最后将记录的结果返回
		return temp;
	}
private:
	int m_number;
};
//重载左移运算符
ostream& operator<<(ostream & cout,Myinteger myint) {
	cout << myint.m_number << endl;
	return cout;
}

void test01() {   //前置递减 --a操作
	Myinteger myint;
	cout << --myint << endl;
	cout << myint << endl;
}
void test02() {  //后置递减  a--操作
	Myinteger myint;
	cout << myint-- << endl;
	cout << myint << endl;
}
int main() {
	test01();
	test02();
	system("pause");
	return 0;
}

赋值运算符重载

赋值运算符重载:对属性进行值拷贝。

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

如果类中有属性指向堆区,做赋值操作时会出现深浅拷贝问题。需要在堆区重新开辟一块内存来存储,否则析构函数连续释放同一块内存会出现错误。

#include<iostream>
using namespace std;

class Person {
public:
	Person(int age) {
		m_age = new int(age);
	}
	~Person() {
		if (m_age != NULL) {    //堆区内存重复释放,程序崩溃。解决方案:进行深拷贝,解决浅拷贝问题
			delete m_age;
			m_age = NULL;
		}
	}


	//重载赋值运算符
	Person &operator=(Person &p) {
		//编译器提供的是浅拷贝操作
		//m_age = p.m_age;

		//应该先判断是否有属性在堆区,如果有先释放干净,再进行深拷贝
		if (m_age != NULL) {    
			delete m_age;
			m_age = NULL;
		}
		//然后再进行深拷贝操作
		m_age = new int(*p.m_age);
		//返回对象本身
		return *this;

	}


	int *m_age;  //想把这个数据开辟到堆区,因此使用指针
};

void test01() {
	Person p1(18);
	Person p2(20);
	Person p3(21);

	//返回对象本身进行一个链式编程来进行赋值操作
	p3 = p2 = p1;//赋值操作
	cout << "p1的年龄为 " << *p1.m_age << endl;    //加上指针对数据进行*解引用,不然会显示一串存储地址
	cout << "p2的年龄为 " << *p2.m_age << endl;
	cout << "p3的年龄为 " << *p3.m_age << endl;

	
}
int main() {
	test01();

	//int a = 10;
	//int b = 10;
	//int c = 10;
	//c = b = a; //内置数据类型允许这种连等的操作
	//cout << a << b << c<<endl;
	system("pause");
	return 0;
}

关系运算符重载

关系运算符重载:可以让两个自定义类型对象进行对比操作。

#include<iostream>
#include<string>
using namespace std;
class Person {
public:
	Person(string name, int age) {
		m_name = name;
		m_age = age;
	}

	//重载关系运算符 ==号
	bool operator==(Person &p) {
		if (this->m_name == p.m_name && this->m_age == p.m_age) {
			return true;
		}
		return false;
	}
	//重载关系运算符!=号
	bool operator!=(Person &p) {
		if (this->m_name == p.m_name && this->m_age == p.m_age) {
			return false;
		}
		return true;
	}

	string m_name;
	int m_age;
};

void test01() {
	Person p1("Amy",18);
	Person p2("Amy",18);
	if (p1 == p2) {
		cout << "p1和p2是相等的" << endl;
	}
	else {
		cout << "p1和p2是不相等的" << endl;
	}
}
void test02() {
	Person p3("Tom", 18);
	Person p4("Jeery", 18);
	if (p3 != p4) {
		cout << "p3和p4是不相等的" << endl;
	}
	else {
		cout << "p3和p4是相等的" << endl;
	}
}

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

函数调用运算符重载

函数调用运算符重载:由于重载后使用的方式非常像函数的调用,因此称为仿函数。仿函数没有固定写法,非常灵活。
匿名函数对象:类型加小括号创建匿名对象,使用完系统直接释放。

#include<iostream>
#include<string>
using namespace std;
class Myprint {
	
public:
	//函数调用()运算符重载
	void operator()(string text) {
		cout << text << endl;
	}
};

void test01() {
	Myprint myprint;
	myprint("hello world!");  //由于使用起来非常类似函数调用,因此称为仿函数
}
void test02(string text) {
	cout <<"test02的函数调用 "<< text << endl;
}
//仿函数非常灵活,没有一个固定的写法
//加法类
class Myadd {
public:
	int operator()(int a,int b) {
		return a + b;
	}
};
void test03() {
	Myadd myadd;
	int result = myadd(100, 100);
	cout <<"result = "<< result << endl;

	//匿名函数对象
	cout << Myadd()(100, 100) << endl;
}
int main() {
	test01();
	test02("hello world!");
	test03();
	system("pause");
	return 0;
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

烬烬今天学习了吗

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值