+加法运算符重载
通过自定义运算符的实现细节,实现自定义数据类型之间的运算。例如自定义一个学生类, 然后定义一个名为operator+的成员函数。
class Student {
public:
Student(int a, string name) { //构造函数
this->age = a;
this->name = name;
}
int age;
string name;
Student operator+(Student &s) const { //通过成员函数重载运算符
// 常函数,常函数内不可修改成员属性,在大括号前加const
Student temp(0,"0");
temp.age = this->age + s.age;
temp.name = this->name + s.name;
return temp;
}
};
在这个例子中,学生类有两个属性,一个是名字、一个是年龄。以+号的运算符重载为例,显然学生a和学生b不像两个数字一样可以直接相加而得出结果,这时我们可以自定义两个学生对象相加的结果。例如假设学生a和学生b相加得学生c,他的名字是学生a和学生b各自的名字相加,年龄是两个学生各自的年龄相加。
Student s2 = Student(18,"s");
Student s1 = Student(2,"a");
Student p = s2 + s1;
得到结果是
name c:sa age c:20
其实现的本质是
p = s2.operator+(s1) //调用s2的operator+方法
也可以通过全局函数实现运算符重载,例如
Student operator+(Student &a,Student &b){ //运算符重载 全局函数
Student temp(0,"0");
temp.age = a.age + b.age;
temp.name = a.name + b.name;
}
原理类似。并且运算符重载也可以进行函数重载(作用域&名称相同、且参数的类型|个数|顺序不同),例如我想再实现Student和int型的相加,只要定义一个同名函数,形参是一个Student和一个int型,再写函数体就行了。
同理,可实现+、<<、++、=、==、<、>、()的重载。
<< 左移运算符重载
打印自定义的数据类型,全局函数,ostream标准输出流类型(不能更改)
ostream & operator<< (ostream & i,Student & s){
//一般只用全局函数重载左移运算符,参数和返回值都是引用
cout << "Operator overloading << "<< s.age << s.name << endl;
//自定义打印规则
return i;
//返回引用为了连续链式的写多个左移
}
cout << p << endl; //调用
++递增运算符重载
前置++
成员函数,返回对象自身的引用,即*this;自定义加法规则。
Student & operator++(){
/*重载前置++运算符,must return with &,否则形如 ++(++i)会使
第二次++操作的是第一次++由产生的新对象(返回值的拷贝构造)而不对最初的i*/
name = name + "x";
age++;
return *this;
}
后置++
返回值,用int作为占位参数以函数重载,必须是int。因为后置++是先用再加,故记录下原本的值,加完再返回原本的值。
Student operator++(int){
/*重载后置++,必须写int作为占位参数,且必须是int,不能是float之类。
否则和重载前置++的函数仅返回值不同,无法函数重载。和前置++不同,必须返回值,
否则返回的引用是temp,是局部变量。
先记录初始值,再运算,最后返回初始值。*/
Student temp = *this;
name = name + "x";
age ++;
return temp;
}
=赋值运算符重载
成员函数;因为直接赋值会产生浅拷贝的问题,所以对指针属性需要自定义复制规则,new一个新地址保存数据,形参是引用,返回值是自身的引用
Student & operator= (Student & s){ //重载赋值运算符=,为了避免浅拷贝的问题
if (s.high != NULL){ //high是一个指针,如果已存在就删去
delete high;
high = NULL;
}
high = new int (*s.high); //深拷贝
return *this;
}
关系运算符重载
< > == !=
成员函数;返回bool类型,自定义大于小于等于不等于的规则。
bool operator==(Student & s){ //返回bool类型
if (this->name == s.name && this->age == s.age){
return true;
}
return false;
}
函数调用运算符重载
重载小括号(),又称仿函数,没有固定写法,非常灵活。
class myPrint{
public:
void operator()(string s){ //重载小括号
cout <<"myPrint:" << s << endl; //函数体
}
};
int main(){
myPrint m; //实例化
m("hello"); //直接小括号传参,很像函数
return 0;
}
输出结果为
myPrint:hello
再举一个例子,有int型返回值
class myAdd{
public:
int operator()(int num1,int num2){
cout << "myAdd:" << num1 + num2 << endl;
}
};
int main(){
myAdd m;
m(1,2);
return 0;
}
输出为
myAdd:3
另外,使用匿名对象可以更方便的使用仿函数,例如
myAdd()(1,2)
myAdd()为创捷一个匿名对象,又由于重载了小括号,所以直接调用了函数运算符重载并传参,等同于先实例化再调用,区别是匿名对象会在使用完后被立即销毁。