运算符我们在程序中经常使用,数学运算符,赋值运算符,比较运算符等。我们可以使用这些运算符对一些基本类型(int,float,double等)进行运算。但是,是没有办法对自定义的类型进行运算的。
但是,如果我们想要对我们自定义的数据类型进行运算怎么办呢?
比如,我们定义一个类,创建两个类对象,我们直接对这两个类对象进行运算,如果直接运算是做不到的,这时候就需要我们使用运算符重载函数来实现了。
运算符重载函数可以有两种形式,成员函数和全局函数。
成员函数: 编译器会自动传入一个调用此函数的对象,所以使用成员函数可以少传一个参数。
全局函数: 需要传入所有参数。
一: 重载的运算符
重载的运算符一般都为二元或者一元的。
对于运算符重载函数,一元只需要一个参数(调用函数的一方),二元需要两个(调用函数的一方和参与运算的一方)。
二: 对于谁调用重载函数
在程序中,对于一元运算符,调用函数的是参与运算的, 对于二元运算符,调用函数的是运算符左侧的函数。
三: 重载函数的参数个数
成员运算符重载函数: 一元: 没有参数 二元: 一个参数
全局友元运算符重载函数: 一元: 一个参数 二元: 两个参数
四: 哪些运算符不可以重载
c++规定,赋值运算符=,x下标运算符[],函数调用运算符(),箭头运算符->只能在函数类内部作为成员函数进行重载。
五: 哪些运算符只能在类中重载
长度运算符sizeof, 条件运算符:?,成员选择符.,域解析运算符:: 是不能够进行重载的。
其余的运算符都可以重载。(但是有些不常用)
六: 重载后运算符的优先级是否修改
我们在运算的时候,运算符是有优先级的, 2+5*8是先计算乘法。
运算符重载不会改变运算符的优先级。
对+,-,*,/等数学运算符进行重载。
class Human {
public:
Human(int age, int salary, const char* name);
Human operator+(const Human& man);
int getAge()const;
private:
int age;
int salary;
string name;
};
int main(void) {
Human man1(18,15000,"ABC");
Human man2(19, 20000, "BCD");
// Human man3 = man1.operator+(man2);
Human man3 = man1 + man2;
cout << man3.getAge() << endl; // 37,man3是man1和man2两个对象年龄的和
system("pause");
return 0;
}
Human::Human(int age, int salary, const char* name)
{
this->name = name;
this->salary = salary;
this->age = age;
}
/*
对象相加的本质还是对其内部的基本类型的数据进行相加,
所以,相加的时候是按照我们指定的相应规则进行相加的。
此处只需要对Human类对象的年龄进行相加
*/
Human Human::operator+(const Human& man)
{
int age_tmp = man.age + this->age;
return Human(age_tmp, man.salary, (man.name).c_str());
}
int Human::getAge() const
{
return age;
}
上面的代码是使用局部函数实现+运算符的重载。
1. 使用运算符重载函数,对类对象进行相加,其实是对其内部的相应数据进行相加,有些数据不需要相加,所以我们运算符重载函数需要根据一定的规则对相应数据进行运算。
2. 上面代码,我们定义了Human类的两个对象,然后对对象进行相加。-- 按照规则: 对对象中的年轻进行相加。
3. Human operator(const Human& man); 是成员函数+运算符重载函数的原型。
在这个方法中对两个对象的age进行相加,存放在age_tmp中,在返回是创建新的对象返回。赋值给man3。最后我们打印,man3.age 结果为37。
class Human {
public:
Human(int age, int salary, const char* name);
friend Human operator+(const Human& man1, const Human& man2);
int getAge()const;
private:
int age;
int salary;
string name;
};
int main(void) {
Human man1(18,15000,"ABC");
Human man2(19, 20000, "BCD");
// Human man3 = operator+(man1,man2);
Human man3 = man1 + man2;
cout << man3.getAge() << endl; // 37,man3是man1和man2两个对象年龄的和
system("pause");
return 0;
}
Human::Human(int age, int salary, const char* name)
{
this->name = name;
this->salary = salary;
this->age = age;
}
Human operator+(const Human& man1, const Human& man2) {
int age_tmp = man1.age + man2.age;
return Human(age_tmp, man1.salary, man1.name.c_str());
}
int Human::getAge() const
{
return age;
}
1. 上面代码使用全局函数实现了+运算符重载,按照规则,我们在+运算符重载函数中对两个对象的age属性进行相加。所以在函数中我们需要访问对象内部的私有属性。
但是此时运算符重载函数是全局函数,不是类内部的成员函数,所以它是没有办法直接访问类内的私有属性呢? 当然你定义公共接口去访问当然没问题,但是比较麻烦。
我们可以将这个运算符函数设置为类内的友元函数,这样就可以访问类内部的私有属性了,会比较方便。
2. Human operator+(const Human& man1, const Human& man2); 是友元全局函数的声明,其实和成员函数类似,就是多了一个参数。
3. 此处为+运算符重载,其余的数学运算符重载函数和+运算符重载函数类似。
上面我们使用成员函数和全局函数分别实现了+运算符的重载。其实看起来两者区别并不大。
区别就是: 使用成员函数,编译器会自动传入调用运算符重载函数对象,不需要我们自己传入,所以可以少写一个参数。(从上述的代码中也能看出来)