c++笔记(九)之核心编程(五)运算符重载

 一.加法运算符重载 

  • 实现两个自定义类型的数据的加法
  • 可以实现person+person
  • 也可以实现person+int(函数重载)
#include<iostream>
using namespace std;
#include<string>


class person
{
public:
	成员函数的重载
	/*person operator+(person p)
	{
		person temp;
		temp.m_A=this->m_A+p.m_B;
		temp.m_B=this->m_A+p.m_B;
		return temp;
	}*/
	int m_A;
 	int m_B;
	
};

全局函数的重载
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& p1, int a)
{
	person temp;
	temp.m_A = p1.m_A + a;
	return temp;
}
void test01()
{
	person p1;
	p1.m_A = 10;
	p1.m_B = 20;
	person p2;
	p2.m_A = 10;
	p2.m_B = 20;

	//成员函数重载本质调用
	//person p3 = p1.operator+(p2);
	//全局函数重载本质调用
	//person p3 = operator+(p1, p2);
	person p3=p1+p2;
	//运算符重载 也可以发生函数重载
	person p4 = p1 + 10;
	cout << "p3.m_A=" << p3.m_A << endl;
	cout << "p3.m_B=" << p3.m_B << endl;
	cout << "函数重载p4.m_A=" << p4.m_A << endl;
}

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

 二.左移运算符

  • 利用运算符重载将不同的
  • 然后因为成员函数最后形成的格式是p<<cout,不符合我们想要的结果;所以只能用全局函数进行重载;
  • 然后假设左移运算符输出的值是类内的私有化成员,则需要用到前边学到的友元,使其能访问。
#include<iostream>
using namespace std;
#include<string>

class person
{
	friend void operator<<(ostream& cout, person& p);
public:
	person(int a, int b)
	{
		m_A = a;
		m_B = b;
	}
private:
	利用成员函数来重载 左移运算符 p.operator<<(cout) 简化版本p<<cout
	// 因为简化后的形式不是我们想要的,所以一般不用成员函数去写左移重载
	//void operator<<(cout)
	//{
	//}
	int m_A;
 	int m_B;
};
//用全局函数重载作为左运算符
//cout 属于标准的输出流对象ostream
//本质operator<<(cout ,p)可简化为cout <<p
void operator<<(ostream &cout,person &p)//这样写返回的不是cout,在cout后不能加endl
//更改:ostream &void operator <<(ostream &cout,person &p)   这样返回值就是输出流了
{
	cout << "m_A:" << p.m_A << "m_B:" << p.m_B;
}
void test01()
{
	person p1(10,20);
	/*p1.m_A = 10;          因为m_A,m_B被私有化了,所以要创建一个构造函数,对接类内的函数与类外的函数数
	p1.m_B = 20;*/
	cout << p1;

	person p2(10,20);
	/*p2.m_A = 10;
	p2.m_B = 20;*/
	cout << p2;
}

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

三.递增运算符重载

  1. 前置和后置重载的区分

  • 是否有占位参数int

前置    operator++()

后置    operator++(int)

  • 返回的值

前置    返回的是引用    person& operator()

后置    返回的是值        person operator(int)

2.代码

#include<iostream>
using namespace std;
#include<string>

class person
{
	friend ostream& operator<<(ostream& cout, person p);
public:
	//前置++    返回引用是为了一直对一个数据进行递增操作
	person operator++()
	{
		m_A++;
		return *this;
	}
	//后置++     返回的是值
	//int 代表的是占位参数,可以区分前置和后置
	person operator++(int)
	{
		//先    记录当时的结果
		person temp = *this;
		//后    递增
		m_A++;
		//最后将记录结果返回
		return temp;
	}
private :
	int m_A=0;
};

ostream& operator<<(ostream& out, person p)  //把ostream自身(引用)作为一个返回
{
	out << p.m_A;
	return out;
}

void test01()
{
	person p1;
	cout << ++(++p1)<<endl;
}

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

四.赋值运算符重载

C++编译器至少给一个类添加4个函数

  1. 默认构造函数(无参   函数体为空)
  2. 默认析构函数(无参   函数体为空)
  3. 默认拷贝构造函数,对属性进行值拷贝
  4. 赋值运算符 operator=  对属性进行值拷贝

前3个函数详情见  此

如果类中有属性指向堆区,对属性进行值拷贝

#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.mage;
			
		//应该先判断是否有属性在堆区,如果有,应该先释放干净,在深拷贝
		if (m_age != NULL)
		{
			delete m_age;
			m_age = NULL;
		}
		m_age = new int(*p.m_age);
		return *this;
		}
	int *m_age=0;
	int m_B;
};

void test01()
{
	person p1(18);
	person p2(20);
	person p3(30);
    p3=p2 = p1;
	cout << "p1的年龄" <<*p1.m_age << endl;
	cout << "p2的年龄" << *p2.m_age << endl;
	cout << "p3的年龄" << *p3.m_age << endl;
}

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

五.关系运算符重载

自定义类型的对比

#include<iostream>
#include<string.h>
using namespace std;

class person
{
public:
	person(int age,string name)
	{
		m_age = age;
		m_name = name;
	}
	
	
	//重载==号
	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;
	}
	int m_age;
	string m_name;
};
//重载<<
ostream& operator<<(ostream& cout, person p)
{
	cout << p.m_age << endl;
	cout << p.m_name << endl;
	return cout;
}
void test01()
{
	person p1(18,"Tam");
	person p2(18, "Tam");
	if (p1 == p2)
	{
		cout << "p1和p2是相等的" << endl;
	}
	else
	{
		cout << "p1和p2是不相等的" << endl;
	}
}

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

六.函数调用运算符重载

  • 函数调用运算符{} 也可以发生重载
  • 由于重载后使用的方式非常像函数的调用,因此称为仿函数
  • 仿函数没有固定的写法,非常灵活
#include<iostream>
#include<string.h>
using namespace std;

class Myapoint
{
	void operator()(string test)
	{
		cout << test << endl;
	}

};
//返回空,就只输出字符串
void test01()
{
	Myapoint p1;
	p1("hello world!");//和函数的调用非常像,所以叫做仿函数
}

class Myadd
{
public:
	int operator()(int num1, int num2)
	{
		return num1 + num2;
	}
};
//返回数字,执行加法运算
void test02()
{
	Myadd P2;
	int ret=P2(10, 20);
	cout<<"ret=" << ret << endl;
}


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

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值