C++运算符重载
运算符重载:赋予运算符新的含义,(赋予运算符可以直接操作自定义类型(类或者是结构体))
#include <iostream>
using namespace std;
#include <string>class MM{public://无参的构造函数MM(){}//有参的构造函数MM(string name,int age):name(name),age(age){}void print(){cout<<name<<":"<<age<<endl;}public:string name;int age;
};int main()
{MM girl ("xiaomei",18);MM mm("张三",20);MM object;//下面的➕是不可以的//object=gril+mm;//这里的等号是可以的,因为其会有一个默认的重载函数//object=girl;
}
因此这里的基本运算符是不能直接作用在自定义类型上面的。
因此我们的运算符重载是为了实现基本运算符运用在自定义的类上面,直接操作自定义类型,我们这里不能操作是因为我们这里没有写运算符重载。
基本重载
- 友元函数的方式实现重载
- 类成员函数的方式实现重载
重载函数的基本语法:重载函数的返回值类型+operator+要重载的运算符(参数){函数体};
参数个数:
- 友元重载 重载函数的参数个数等于运算符的操作数
- 类成员函数重载,重载函数的参数个数是等于运算符的操作数-1
测试代码:
//重载函数的返回值类型。operator+要重载的运算符(参数){函数体};
//重载函数的返回值类型:重载函数的返回值,是由重载的运算符表达式的最终结果决定的:a+b,最终得到的肯定是一个对象,所以+重载的函数的返回值类型一定是一个对象
friend A operator+(A a,A b). //运算重载的函数名:operator+
{}
因此看下面演示例子:
#include <iostream>
using namespace std;
#include <string>class MM{public://无参的构造函数MM(){}//有参的构造函数MM(string name,int age):name(name),age(age){}//重载函数friend MM operator+(MM object1, MM object2);void print(){cout<<name<<":"<<age<<endl;}public:string name;int age;
};MM operator+(MM object1,MM object2)
{return MM(object1.name+object2.name,object1.age+object2.age);
}int main()
{MM girl ("xiaomei",18);MM mm("张三",20);MM object;//下面的➕是不可以的object=girl+mm;object.print();//这里的等号是可以的,因为其会有一个默认的重载函数//object=girl;
}
因此下面的运算结果为:
这个结果,也就实现了将基本运算符运用在我们的自定义类型上面。简单一点说就是为了实现对象与对象之间的运算
//友元重载
MM operator+(MM object1,MM object2)
{return MM(object1.name+object2.name,object1.age+object2.age);
}
所有重载的实质都是函数调用
显式调用
int main()
{MM girl ("xiaomei",18);MM mm("张三",20);MM object;//下面的➕是不可以的object=girl+mm;//运算符重载函数的隐式调用object.print();//显式调用//operator+解析为函数名MM xiaomei=operator+(girl,mm);//运算符重载函数的显式调用xiaomei.print();//这里的等号是可以的,因为其会有一个默认的重载函数//object=girl;
}
因此运算符重载依然是支持函数调用的形态它是把这个地方解析为
object=girl+mm;
下面这个函数的调用
MM xiaomei=operator+(girl,mm);
但是我们一般情况下都不会这样去写,一般都是直接用+号直接得出结果。
所谓的显示调用就类似于函数调用一样的用法。
//友元重载把gril+mm过程解析为函数调用的过程
operator+(mm,girl);
这里的=调用的是构造函数
MM xiaomei=operator+(girl,mm);
类成员重载
#include <iostream>
using namespace std;
#include <string>class MM{public://无参的构造函数MM(){}//有参的构造函数MM(string name,int age):name(name),age(age){}//重载函数friend MM operator+(MM object1, MM object2);//类的成员函数的方式重载//减法MM operator-(MM object){return MM(this->name,this->age-object.age);}void print(){cout<<name<<":"<<age<<endl;}public:string name;int age;
};
//友元重载
MM operator+(MM object1,MM object2)
{return MM(object1.name+object2.name,object1.age+object2.age);
}int main()
{MM girl ("xiaomei",18);MM mm("张三",20);MM object;//下面的➕是不可以的object=girl+mm;object.print();//显式调用MM xiaomei=operator+(girl,mm);xiaomei.print();//这里的等号是可以的,因为其会有一个默认的重载函数//object=girl;//调用一下减法MM xiaofang=mm-girl;MM xiaolizi=mm.operator-(girl);xiaofang.print();xiaolizi.print();}
这个this代表类成员属性本身,在这里this代表的是mm,object代表的是girl,为什么呢,因为this指代的是所有的对象的地址的通值,然后我们在
MM operator-(MM object){return MM(this->name,this->age-object.age);}
这个函数里面传递进来了一个object,因此这就是为什么在这里this代表的是mm,object代表的是girl会是这样的结果。
友元函数是类外的函数,因此其里面是没有this的,其实这里的
void print(){cout<<name<<":"<<age<<endl;}
可以写成
void print(){cout<<this->name<<":"<<this->age<<endl;}
这个样子。因此这里的this指的是你哪个对象调用print函数,这个this就是指代的哪个对象。
因此我们用this去访问的时候值的是用类的对象去访问属性。但是不同的函数调用这个方法,这个this指代的是不同的函数。
为什么类成员重载的对象要是少一个的,因为有一个对象是充当这个对象.xx,通过这个点的方式调用,因此虽然其有两个参数,但是有一个已经在前面,另外一个在后面。因此它的解析方式与友元的解析方式是不一样的。上面的相当于调用的是另外的函数,但是下面这个相当于是调用的是另外的一个对象再来执行operator-。
其实还有一种更好理解的方式
void printData(){MM::print();this->print();}
因此单纯的调用一个函数,这两种方法都可以。
this是通址,比如同学是所有学生的通址,比如你只要在学校里面读书,你就是同学。大家都去食堂去吃饭,你来了你可以去食堂去吃饭,其他同学来了,他也可以去食堂去吃饭啊。