C++ 运算符重载

本文详细介绍了C++中的运算符重载,包括其本质是函数调用的封装,以及如何通过重载实现加减乘除、流操作符、前置和后置自增减。还展示了在日期类中整体运用运算符重载的例子。
摘要由CSDN通过智能技术生成

1.运算符重载本质

#include<iostream>
using namespace std;

//运算符重载的本质
/* 运算符实质上也就是一个函数的调用,但实现同一种功能
不同的人会写出不一样的函数以及函数名,
为了减少代码重复率 以及简化函数格式 使用运算符进行计算
*而运算符重载实际上也只是在运算符函数上 通过同样的函数名称:operator 进行运算符函数的扩展
 */
 //下面以+=运算符重载为例
 
 class A
 {	
 public:
 	A(int x)
 {
 	a=x;
 }
 	
 		int a;
 		A& operator+=(A& other)
 //  返回值类型 名称()  		
 		{	
 		this->a+=other.a; //对应属性相加操作 
 		return *this; 
		 }
  } ;
  
void test01()
{
	A x1(4);
	A x2(6);//先初始化两个对象 使用重载运算符对他们进行相加 
	x1+=x2;//符号使其看着美观  
	cout<<"x1+=x2:"<<x1.a<<endl;
	//本质上它调用了这个函数 
	x1.operator+=(x2); 
	cout<<"x1.operator+=(x2):"<<x1.a<<endl;
}
int main()
{
	test01();
}

 

2.加减乘除以及流重载

#include<iostream>
using namespace std;

class one{
	friend ostream & operator<<(ostream & out,one a);
	friend istream & operator>>(istream & in ,one &a);
	friend one operator+(int b,one a);
	friend one operator+(one a,int b);
	public:
		one(int a,int b)
		{
			A=a;
			B=b;
		}
		one(one &x) 
		{
			this->A=x.A;
			this->B=x.B;	
		}
	void get_one()
	{
		cout<<"A="<<A<<endl<<"B="<<B<<endl;
	}
	one operator+(one &y) //函数内部重载加号
	{
		one p(0,0);
		p.A=this->A+y.A;
		p.B=this->B+y.B;
		return p;
		
	 } 
	 
	 void set_one(int a,int b)
	 {
	 	this->A=a;
	 	this->B=b;
	 }
	
	int A;
	int B;
};
// 输出流 << 重载 
ostream & operator<<(ostream & out,const one a)//cout 是 ostream 类型,输出流   <<运算符  p(参数)
//通常定义为全局函数,才能实现 cout << 变量          //cout在左样式     类似: p(1)   +   p(2)
//类内重载  会变成           变量 << cout  形式不美观
{
	out<<"XXX是骗子\n a.A="<<a.A<<endl<<"a.B="<<a.B;
	return out;// 返回 cout 类,(链式编程)实现函数连接性,也就是可以 cout<< a<<b<<···一直加 
 } 
 //输入流 >> 重载 
 istream & operator>>(istream & in ,one *a)
 {
 	in>>a->A>>a->B;
 	return in;
  } 
  istream & operator>>(istream & in,one &a)//记得设置友元  以及检查符号 
  {
  	in>>a.A>>a.B;
  	return in;
  }
  //加减乘除的重载如下
  // 加减乘除重载 主要保证类中对应成员做相应运算 
  //值得注意的是:加减乘除 要保留原来的意思 才不会令人感到困惑
 one  operator+(int b,one a)
 {
 	one c(0,0);
 	c.A=a.A+b;
 	c.B=a.B+b;
 	return c;
  } 
  one operator+(one a,int b)
  {
  	one c(0,0);
 	c.A=a.A+b;
 	c.B=a.B+b;
 	return c;
  }
  // 在全局重载 需要提供两个对象 
  //而且需要注意运算符前后的数据类型,如果数据类型与重载后的运算符前后不对应是无法运行的,也就是函数的形参顺序不对应
one operator-(one &a,one &b)
{
	one c(0,0);
	c.A=a.A-b.A;
	c.B=a.B-b.B;
	return c;
}
one operator*(one &a,one &b)
{
	one c(0,0);
	c.A=a.A*b.A;
	c.B=a.B*b.B;
	return c;
}
one operator/(one &a,one &b)
{
	one c(0,0);
	c.A=a.A/b.A;
	c.B=a.B/b.B;
	return c;
}

int main()
{
	one a(1,2);
	one b(3,4);
/*	a.get_one();
	b.get_one();
	one c(0,0);
	c=a+b;
	c.get_one();
	b.set_one(10,10);
	c=a+b;
	c=a+b+b;
	c.get_one();
	c.set_one(0,0);
	c=b-a+b;
	c.get_one();
	a.set_one(1,1);
	b.set_one(6,6);
	c=a*b;
	c.get_one();
	c=c/b;
	c.get_one();
	cout<<1+1;  */
//	cout<<a<<endl;
	a=a+b;
//	a.get_one();
//	cout<<"a.get_one :"<<a.A<<endl<<a.B<<endl;
	cout<<a<<endl;
//	cout<<a;
/*	cin>>&a;
	cout<<a<<endl;
	cin>>a;
	cout<<a<<endl;  */
	a=100+a;
	cout<<a;
	a=a+1000;
	cout<<a;
// 如何 级联	a=a+100+a+20;
 
	cout<<a;
}

3.++ -- 前置与后置重载

#include<iostream>
using namespace std;

class My_Date
{	friend ostream & operator<<(ostream & cout,const My_Date &a);
	public:
		My_Date(int i,char a,float b)
		{
			num=i;
			c=a;
			f=b;
		}
		//++前置 需要先对操作对象++,然后返回改变后的操作对象
		// 返回引用,是保证对操作对象的数值的改变 当然,也可弄个临时变量,只要对操作对象进行++即可,不过多此一举 
		My_Date & operator++()
		{
			this->num++;
			this->c=c+1;
			this->f++;
			return *this;
		}
		//后置++ 需要返回操作对象本来值,然后进行++操作 
		//实际上 需要临时变量存储 原来的操作对象 ,然后对操作对象变化,最后返回临时变量的值
		//但函数在结束使用后会销毁 导致临时变量地址不存在,所以要返回 新的对象而不是引用 默认call构造函数 做个新对象显示值 
        My_Date operator++(int=0)  //这里的参数是为了区分 前置++ 与 后置++ 
        {
        	My_Date temp=*this;
        	this->num++;
        	this->c++;
        	this->f++;
        	return temp;
		} 
		//类似 可以做--操作
		//
		//--前置
		My_Date & operator--()
		{
			(*this).num--;
			this->c--;
			f--;
			return *this;
		 } 
		 //后置--
		 My_Date operator--(int)
		 {
		 	My_Date temp=*this;
		 	(*this).num--;
			this->c--;
			f--;
		 	return temp;
		  } 
            //  * 
		My_Date & operator*(int a)
		{
			num*=a;
			f*=a;
			return *this;
		}
		My_Date & operator*(My_Date & d)
		{
			num*=d.num;
			f*=d.f;
			return *this;
		}
		// /
		My_Date & operator/(int m)
		{   if(m==0) 
		{
			cout<<"Error 0";
			return *this;
		}
			num/=m;
			f=f/m;
			return *this;
		}
		My_Date & operator%(int m)
		{   if(m==0) 
		{
			cout<<"Error 0";
			return *this;
		}
			num%=m;
			
			return *this;
		}
		
	//private:
		int num;
		char c;
		float f;
};

void test_1()
{	My_Date first(1,'2',3);
	My_Date second(10,'0',30);
}
ostream & operator<<(ostream & cout,const My_Date &a)
{
	cout<<"int="<<a.num<<"\nchar="<<a.c<<"\nfloat="<<a.f<<endl;
	return cout;
}
int main()
{
/*	My_Date one(1,'2',3.5);
	cout<<one;
	cout<<++one;
	cout<<one;
	cout<<one++;
	cout<<one;  */
	My_Date sec(2,'3',4.5);
	cout<<"起始:"<<endl<<sec;
	cout<<"--sec:\n"<<--sec;
	cout<<"666";
	cout<<"sec:\n"<<sec;
	cout<<"sec--:\n"<<sec--;
	cout<<"sec:\n"<<sec;
	
	
}

4.匿名调用  仿函数 判断符重载

利用赋值符重载进行函数深拷贝

#define _CRT_SECURE_NO_WARNINGS

#include<iostream>

#include<string.h>

using namespace std;

class my_printf

{

friend ostream& operator<<(ostream& cout, my_printf& X);

public:

my_printf(int A, string B, char* C)

{

a = A;

b = B;

// 深拷贝前提 每个对象要有独立空间

c = new char[strlen(C) + 1];

strcpy(c,C);

}

my_printf(my_printf& a)

{

*this = a;

}

// 仿函数 与 函数

// 为何刚刚没有返回值类型 也没返回值 也没事 C++中默认void类型返回值

void operator()(my_printf& X) // () 重载 与 函数形式相近 ,故称仿函数

{

cout << X << endl;

}

// 函数

void My_printf(my_printf& X)

{

cout << X << endl;

}

// 判断符重载

bool operator==(my_printf& X)

{

if (a == X.a && b == X.b && (*c) == *(X.c)) return true;

else return false;

}

//深拷贝 利用重载 = 实现

my_printf& operator=(my_printf& X)

{

if (this->c != NULL) //先看原地址是否为空 如果为空 将它变为空指针方便拷贝

{

delete []c; //数组需要加[]销毁

c = NULL;

}

c = new char[strlen(X.c)+1]; //长度加一为了最后一个位置存放空字符

strcpy(c, X.c);

a = X.a;

b = X.b;

return *this;

}

int a;

string b;

char* c;

};

ostream& operator<<(ostream& cout, my_printf& X)

{

cout << "int=" << X.a << endl

<< "string=" << X.b << endl

<< "c=" << X.c << endl;

return cout;

}

//void test01()

//{

// string b = "十";

// char* d = "66";

// my_printf X1(10, b, d);

// X1(X1);// 仿函数

//}

//void test02()

//{

// char* D = "77";

// string B = "十一";

// my_printf X2(20, B, D); //有头有脸

// X2.My_printf(X2);//函数

// X2(X2);//仿函数

// my_printf(30, B, D)(X2); // 匿名调用 仿函数 这一行结束,所创立对象就会销毁 无名之辈 故称匿名

// my_printf(30, B, D).My_printf(X2); // 匿名调用 其他成员

// cout << my_printf(30, B, D).a; // 甚至如此 不过这一句执行完就销毁,如果只用一次,挺不错

//

//}

int main() {

//test01();

//test02();

string b = "20";

char a[5] = "1234";

my_printf X1(5, b,a );

my_printf X2(9, b, a);

X1 = X2;// 可以重载=实现深拷贝,当然也可以直接构造函数进行深拷贝

if (X1 == X2) cout << "True\n";

else cout << "Fasle\n";

my_printf X3(X2);

X2(X3);

if (X3 == X2) cout << "True\n";

else cout << "Fasle\n";

}

5.案例:用Date整体运用运算符重载 

#include<iostream>
using namespace std;

class Date{
	friend ostream & operator<<(ostream & cout,const Date &a );
	friend istream & operator>>(istream & cin,Date &a);
	public:
		static const int days[];
		Date(int y,int m,int d)
		{
			set_Date(y,m,d);
		}
		Date &set_Date(int y,int m,int d)
		{
			year=y;
			
			month=m;
			if(!RN()&&month==2&&d==29)
			{
				day=1;
				cout<<"Please check your input !!! RN!!!";
			}
			
		/*	day=d;
			if(day>days[month]) 
			{
				day=1;
				cout<<"Please check your input!!!";
			}
		*/
		   day=(d>days[month]?1:d);
			return *this;
		}
		bool RN()
		{
			if(((year/100!=0)&&(year/4==0))||(year/400==0))
			  return true;
			return false;
		}
		Date & operator++() //前加加 
		{  	
			if(end_day()) 
			{
				if(month==12) 
				{
					year++;
					day=1;
					month=1;
				}
				else 
				{day=1;
				month++;
				}
			}
			else day++;
			return *this;
		}
		// 后--
		Date operator--(int )
		{
			Date temp=*this;
			if(first_day()&&month==1)
			{
				year--;
				month=12;
				day=31;
			 } 
			 else if(first_day()) 
			 {
			 	month--;
			 	day=days[month];
			 }
			 else day--;
			 return temp;
		 } 
		bool first_day()
		{
			if(day==1) return true;
			else return false;
		}
		
		bool end_day()
		{
			if(RN()&&month==2&&day==29)  return true;
			else 
				if(month!=2&&day==days[month]) return true;
				else return false;
		
		}
		Date & get_Date()
		{
			cout<<year<<"/"<<month<<"/"<<day<<endl;
			return *this;
		}
		Date & operator+=(int add)// += 
		{
			for(int i=0;i<add;i++)
			operator++();
			return *this;
		}
	private:
		int day;
		int month;
		int year;
		
		
};
const int Date::days[]={0,31,28,31,30,31,30,31,31,30,31,30,31};
ostream & operator<<(ostream & cout,const Date &a ) //输出流 重载 
{
	cout<<a.year<<"/"<<a.month<<"/"<<a.day<<endl;
			return cout;
}
istream & operator>>(istream & cin,Date &a) // 输入流重载 
{
	cout<<"请分别输入年月日(用空格分隔)"<<endl;
	cin>>a.year>>a.month>>a.day;
	return cin;
}
int main()
{
	Date myday(2004,5,1);
	cin>>myday;
	myday.get_Date();
	++myday;
	cout<<myday;
	cout<<myday--;
	cout<<myday;
	/*myday+=30;
	cout<<myday; */
	
}

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值