文章目录
1. 加号运算符重载
1.1 成员函数
#include <iostream>
#include<string.h>
using namespace std;
//重载加号之成员函数的重载
class Point
{
public:
int x;
int y;
Point():x(1),y(1)
{
}
Point operator+(Point &p)
{
Point temp;
temp.x+=p.x;
temp.y+=p.y;
return temp;
}
};
int main()
{
Point p1;
Point p2;
Point p3=p1+p2;
cout<<p3.x<<" "<<p3.y<<endl;
}
注:Point p3=p1+p2;
的本体是Point p3=p1.operator+(p2);
为方便记忆,编译器可以帮忙自动转换。
1.2 全局函数
#include <iostream>
#include<string.h>
using namespace std;
//重载加号之成员函数的重载
class Point
{
public:
int x;
int y;
Point():x(1),y(1)
{
}
};
Point operator+(Point &p1,Point &p2)
{
Point temp;
temp.x=p1.x+p2.x;
temp.y=p1.y+p2.y;
return temp;
}
Point operator+(Point &p1,int num)
{
Point temp;
temp.x=p1.x + num;
temp.y=p1.y;
return temp;
}
int main()
{
Point p1;
Point p2;
Point p3=p1+p2;
cout<<p3.x<<" "<<p3.y<<endl;
Point p4=p1+ 4;
cout<<p4.x<<" ";
}
2. 左移运算符重载
2.1 成员函数
<<一般不利用成员函数重载,因为cout<<p;
一般是cout在左边p在右边,但是如果调用成员函数的话就是p.operator<<cout
,编译器会简化成p<<cout;
2.2 全局函数
#include <iostream>
#include<string.h>
using namespace std;
//重载左移运算符之成员函数的重载
class Point
{
public:
int x;
int y;
Point():x(1),y(1)
{
}
};
ostream& operator<<(ostream& cout,Point p)
{
cout<<"p.x:"<<p.x<<" "<<"p.y:"<<p.y<<endl;
return cout;
}
//注:要写成返回值是ostream&类型,不然下面的main函数中p1后不能再进行链式编程,如p1<<endl
int main()
{
Point p1;
cout<<p1<<endl;
}
注:cout<<p1;
的本体是<<(cout,p1)
为方便记忆,编译器可以帮忙自动转换。<<(cout,p1)
返回的是一个ostream&类型的cout,而cout后面是可以加<<的也就是说,<<(cout,p1)
后面又是可以直接加<<的,这也是链式编程的一种思想。
3. 递增运算符重载
目的:我们进行递增运算符重载,是为了让我们自己的数据类型MyInteger能够实现:
MyInteger myInteger;
++ myInteger;//或myInteger++;
3.1 成员函数
3.1.1 前置递增
#include <iostream>
using namespace std;
class MyInteger
{
public:
// 为了让operator能够访问integer.m_integer
friend ostream& operator<<(ostream& cout,MyInteger integer);
MyInteger()
{
m_integer = 0;
}
// 前置递增 ++a
MyInteger& operator++()
{
m_integer++;
return *this;//这里的*this代表的是main或者其他函数中由MyInteger m;而创建出来的指向m这个对象的指针
}
int m_integer;
};
// 为了能够 cout<<myinteger;需要先重载一下<<左移运算符
ostream& operator<<(ostream& cout,MyInteger integer)
{
cout<<integer.m_integer;
return cout;
}
int main()
{
MyInteger myinteger;
cout<<"myinteger:"<<myinteger<<endl;
cout<<"++myinteger:"<<++myinteger<<endl;
return 0;
}
3.1.2 后置递增
#include <iostream>
using namespace std;
class MyInteger
{
public:
// 为了让operator能够访问integer.m_integer
friend ostream& operator<<(ostream& cout,MyInteger integer);
MyInteger()
{
m_integer = 0;
}
// 前置递增 ++a
MyInteger& operator++()
{
m_integer++;
return *this;//这里的*this代表的是main或者其他函数中由MyInteger m;而创建出来的指向m这个对象的指针
}
// 后置递增 a++
MyInteger operator++(int)//这里为什么不用MyInteger返回temp的引用呢?原因很简单。返回局部变量的引用是非法的。
{
MyInteger temp = *this;
m_integer++;
return temp;
}
int m_integer;
};
// 为了能够 cout<<myinteger;需要先重载一下<<左移运算符
ostream& operator<<(ostream& cout,MyInteger integer)
{
cout<<integer.m_integer;
return cout;
}
int main()
{
MyInteger myinteger;
cout<<"myinteger:"<<myinteger<<endl;
cout<<"++myinteger:"<<++myinteger<<endl;
cout<<"myinteger++:"<<myinteger++<<endl;
return 0;
}
3.2 全局函数【是没有的,我自己瞎写的】
3.2.1 前置递增
#include <iostream>
using namespace std;
class MyInteger
{
public:
// 为了让operator能够访问integer.m_integer
friend ostream& operator<<(ostream& cout,MyInteger &integer);
friend MyInteger& operator++(MyInteger& integer);
MyInteger()
{
m_integer = 0;
}
int m_integer;
};
// 为了能够 cout<<myinteger;需要先重载一下<<左移运算符
ostream& operator<<(ostream& cout,MyInteger &integer)
{
cout<<integer.m_integer;
return cout;
}
//++a
MyInteger& operator++(MyInteger& integer)//之所以返回&而不是返回值,因为一直要对一个数据进行操作,比如++(++a)
{
integer.m_integer++;
return integer;
}
int main()
{
MyInteger myinteger;
cout<<"myinteger:"<<myinteger<<endl;
cout<<"++myinteger:"<<++myinteger<<endl;
// cout<<"myinteger++:"<<myinteger++<<endl;
return 0;
}
3.2.2 后置递增
a++,似乎是实现不了,因为如果实现的话operator++()里没参数就没办法实现对前面的值++,在网上也没见到有人用全局函数做重载递增的。
4. 赋值运算符重载
与难点六(深拷贝、浅拷贝)一样,这里也会出现深浅拷贝问题,也即开辟在堆区的数据重复析构。我们可以看一下错误的来源:
#include <iostream>
#include <string.h>
using namespace std;
class Person
{
public:
Person(string name)
{
m_name = new string(name);
}
~Person()
{
if (m_name!=NULL)
{
delete m_name;
m_name=NULL;
}
}
string* m_name;
};
int main()
{
Person p1("Tom");
Person p2=p1;
return 0;
}
不加这个析构函数的时候貌似风平浪静,但是实际上暗流涌动。加上析构,立马表现出与深浅拷贝析构一样的不干净。
解决问题:
#include <iostream>
#include <string.h>
using namespace std;
class Person
{
public:
Person(string name)
{
m_name = new string(name);
}
Person& operator=(Person& p2)
{
if(m_name!=NULL)
{
delete m_name;
m_name=NULL;
}
m_name= new string(*p2.m_name);
return *this;
}
~Person()
{
if (m_name!=NULL)
{
delete m_name;
m_name=NULL;
}
}
string* m_name;
};
int main()
{
Person p1("Tom");
Person p2("Jerry");
p2=p1;
cout<<*p2.m_name;
return 0;
}
注意:这里的重载函数的参数一定要以引用或者指针的形式传入,不然在传入的时候进行了一次拷贝将赋值右边p2的值传入的时候临时变量记录的p2的属性m_Age的地址,而出了赋值运算符重载函数会进行一次析构 这时p2的属性new出来的空间已经被释放了,最后结束调用虽然你深拷贝了但是程序还是会崩
【这地方我也有点迷 学的时候是大半夜迷迷糊糊的 以后找个机会要复习一下】
5. 关系运算符重载
自定义数据类型的比较(相等与不相等)
#include <iostream>
#include <string.h>
using namespace std;
class Person
{
public:
Person(string str,int Age):name(str),age(Age)
{
}
bool operator==(Person &p2)
{
if (this->name==p2.name&&this->age==p2.age)
return 1;
else
return 0;
}
bool operator!=( Person &p2)
{
if (this->name!=p2.name||this->age!=p2.age)
return 1;
else
return 0;
}
string name;
int age;
};
int main()
{
Person p1("Tom",18);
Person p2("Tom",19);
if(p1==p2)
{
cout<<"相等"<<endl;
}
else
cout<<"不相等"<<endl;
if(p1!=p2)
{
cout<<"不相等"<<endl;
}
else
cout<<"相等"<<endl;
return 0;
}
6. 函数调用运算符重载(仿函数)
6.1“仿函数”名称的来源
由于调用的格式非常像一个函数,所以又称为仿函数。
#include <iostream>
#include <string.h>
using namespace std;
class Point
{
public:
void operator()()
{
cout<<"operator()的调用"<<endl;
}
void operator()(string num)
{
cout<<"operator(string num)的调用"<<endl;
}
};
int main()
{
Point point;
point.operator()();//原本应该这么调用
point();//编译器简化以后可以这么调用
point.operator()("xiaoming");//原本应该这么调用重载函数
point("xiaoming");//编译器简化后的重载函数的调用
return 0;
}
6.2 函数的参数列表、返回值都比较灵活
例:
#include <iostream>
#include <string.h>
using namespace std;
class Point
{
public:
void operator()()
{
cout<<"operator()的调用"<<endl;
}
void operator()(string num)
{
cout<<"operator(string num)的调用"<<endl;
}
int operator()(int a,int b)
{
cout<<"int operator()(int a,int b)的调用"<<endl;
return a+b;
}
};
int main()
{
Point point;
point.operator()();//原本应该这么调用
point();//编译器简化以后可以这么调用
point.operator()("xiaoming");//原本应该这么调用重载函数
point("xiaoming");//编译器简化后的重载函数的调用
cout<<point(3,4);
return 0;
}
6.3 匿名对象(匿名函数对象)
如果不想创建对象,那就写一个匿名的,当前行执行完立即被释放。而因为里面又有函数重载了一个小括号,所以称之为匿名函数对象。第一个小括号,说明是在创建匿名对象;第二个小括号,说明是在使用重载的()运算符。
例:
#include <iostream>
#include <string.h>
using namespace std;
class Point
{
public:
void operator()()
{
cout<<"operator()的调用"<<endl;
}
void operator()(string num)
{
cout<<"operator(string num)的调用"<<endl;
}
};
int main()
{
Point()();
Point()("xiaoming");//编译器简化后的重载函数的调用
return 0;
}