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; */
}