运算符重载:对已有的运算符重新进行定义,赋予另一种功能,以适应不同的数据类型
加号运算符重载:实现两个自定义数据类型相加的运算
可以通过成员函数重载+号
关键字 operator+
person operator+ (person &p);
完成函数后
person p1;
person p2;
不必写p1.operator+(p2);
只需要 p1+p2;
也可以通过全局函数重载+号
使用的时候也只需要p1+p2
运算符重载也可以发生函数重载
即给+赋予更多的对于不同参数的功能
内置的数据类型表达式运算符不能改变; 不要滥用运算符重载
左移运算符重载:可以输出自定义数据类型
person p;
cout<<p<<endl;
不会利用成员函数重载<<运算符,因为无法实现cout在左侧,本质是cout operator<<p
用全局函数重载左移运算符
ostream cout标准输出流对象,这个对象全局只能有一个,不能拷贝,所以需要用引用的方式
void operator<<(ostream &cout, person &p)
{
cout<<p.a<<p.b<<endl;
}
上述代码只能调用cout<<p,因为返回值为void,无法进行链式编程,要改变返回值为
ostream & operator<<(ostream &cout, person &p)
{
cout<<p.a<<p.b<<endl;
return cout;
}
可以调用cout<<p<<"ddd"<<endl;
重载左移运算符配合友元可以实现输出自定义类型
递增运算符重载:通过重载递增运算符,实现自己的整型数据
成员函数,类中定义了私有成员变量a;
前置
person& operator++()返回引用是为了一直对一个数据进行递增
{
a++;
return *this;
先做++运算,再做自身返回
}
后置
person operator++(int)//int为占位参数,用于区分前置和后置递增
不能返回引用因为此时返回的是局部变量
{
先记录在递增
person temp=*this;
a++;
return temp;
}
前置递增返回引用,后置递增返回值
赋值运算符重载
C++编译器至少给一个类添加四个函数
1默认构造函数
2默认析构函数,均无参函数体为空
3默认拷贝构造函数,对属性进行值拷贝
4赋值运算符 operator=,对属性进行值拷贝
如果类中有属性指向堆区,做赋值操作时也会出现深浅拷贝问题
如果不写特别的赋值,存在堆区数据时,普通赋值会进行浅拷贝,析构堆区就会造成重复释放
成员函数完成重载:
person& operator=(person &p)
{此时的a为指针,指向一块堆区数据int *a=new int (10);
编译器提供的如:a=p.a;
要写的为:
先判断是否有属性在堆区,如果有先释放干净,然后再进行深拷贝
if(a!=NULL)
{
delete a;
a=NULL;
}
a=new int(*p.a);深拷贝
return *this;保证返回值,完成链式操作
}
为了满足链式操作,需要进行更改
关系运算符重载
重载关系运算符,可以让两个自定义类型对象进行对比操作
成员函数重载
bool operator==(person &p)
{
if(this->name==p.name&&this->age==p.age)return ture;
return false;
}
函数调用运算符()也可以重载
由于重载后使用的方式非常像函数的调用,因此成为仿函数
仿函数没有固定写法,非常灵活
成员函数实现
void operator()(string test)
{
cout << test <<endl;
}
使用的时候
void test()
{
person p;
p("hello world");将会输出hello world 仿函数
调用正常函数,test2(“hello world”);非常相似
匿名函数对象,完成后立即被释放,空的小括号就代表他
person()(“hello world”);
}