前言
很多的语言不支持operator overloading,不建议overload logic and和logic or
示例
最基本的重载
首先我们重载就和写一个函数一样,先定义返回值,再加上关键字operator,紧接着的是重载的运算符,最后是2个参数,如下
struct Complex{
double r;
double i;
};
Complex operator+(const Complex &lhs, const Complex &rhs){
return Complex{lhs.r + rhs.r, lhs.i + rhs.i};
}
int main(){
Complex c{1,2};
const auto result = c + Complex{3,4};
假设重载要操作的数字属于private的
假设重载要操作的数字属于private的,此时我们就要将重载的函数写入到类中
struct Complex{
Complex(const double R, const double I)
: r{R}, i{I}{
}
Complex operator+(const Complex &rhs){
return Complex{r + rhs.r, i +rhs.i};
}
private:
double r;
double i;
};
/** 因为Complex::r和Complex::i已经变得私有,所以下面的重载函数不再起作用,我们的重载函数要写在结构里面
Complex operator+(const Complex &lhs, const Complex &rhs){
return Complex{lhs.r + rhs.r, lhs.i + rhs.i};
}
**/
int main(){
Complex c{1,2};
const auto result = c + Complex{3,4};
}
假设重载后操作的另一个值只有一个,而我们的类有多个成员变量
首先我们要明白,假如我们重载后,一个class或者struct通过重载的运算符去操作另一个对象,另一个对象不管是什么(比如常量)都会被隐式的转换成操作符定义的对象,假设我们的操作符重载后,其定义的第二个操作对象还是struct Complex
,但是我们实际使用的时候操作符重载后定义的第二个操作对象输入的是一个常量(此时会将这个常量隐式的转换成struct Complex
),而struct Complex
有2个成员变量,所以此时我们要写一个构造函数,使其可以输入一个值,如下
struct Complex{
Complex(const double R) //3.5隐式的转换成struct Complex的时候会调用这个构造函数
: r{R}, i{0}{
}
Complex(const double R, const double I)
: r{R}, i{I}{
}
Complex operator+(const Complex &rhs){
return Complex{r + rhs.r, i +rhs.i};
}
private:
double r;
double i;
};
/** 因为Complex::r和Complex::i已经变得私有,所以下面的重载函数不再起作用,我们的重载函数要写在结构里面
Complex operator+(const Complex &lhs, const Complex &rhs){
return Complex{lhs.r + rhs.r, lhs.i + rhs.i};
}
**/
int main(){
Complex c{1,2};
const auto r = c + 4.5; //这里在重载的时候将加号右边的4.5转换成Complex,但是这里只有4.5一个变量,所以我们构造函数专门给他写了一个单变量的构造函数
const auto result = c + Complex{3,4};
}
operator需要隐式转换的对象在重载后的操作符左边
假设我们想一个问题auto r = 4.5 + c
此时上述的代码就不再起作用,因为需要隐式转换的对象在重载后的操作符左边,那么此时我们应该在struct中将操作符2侧的对象都写完
struct Complex{
Complex(const double R)
: r{R}, i{0}{
}
Complex(const double R, const double I)
: r{R}, i{I}{
}
Complex operator+(const Complex &rhs){
return Complex{r + rhs.r, i +rhs.i};
}
friend Complex operator+(const Complex &lhs, const Complex &rhs){//不加这个重载函数4.5 + c就会报错
return Complex{lhs.r + rhs.r, lhs.i + rhs.i};
}
private:
double r;
double i;
};
/** 因为Complex::r和Complex::i已经变得私有,所以下面的重载函数不再起作用,我们的重载函数要写在结构里面
Complex operator+(const Complex &lhs, const Complex &rhs){
return Complex{lhs.r + rhs.r, lhs.i + rhs.i};
}
**/
int main(){
Complex c{1,2};
const auto r = c + 4.5; //这里在重载的时候将加号右边的4.5转换成Complex,但是这里只有4.5一个变量,所以我们构造函数专门给他写了一个单变量的构造函数
const auto z = 4.5 + c;
const auto result = c + Complex{3,4};
}
假设我们不加上friend
关键字,将其定义成友元函数,那么我们4.5+c
中的4.5不能访问这个重载函数(Complex operator+(const Complex &lhs, const Complex &rhs)
),因为4.5不是struct Complext的对象,只有先访问了这个重载函数,4.5才能隐式的转换成Complex结构
通过上述的例子,我们一定要注意重载函数的domain
假设重载函数非inline,或者没有加上Class::
.那么此重载函数不属于class的domain中,我们可以在外面很畅快的使用他,但是重载函数操作的数据是private的那么,重载函数就不能直接调用private的成员),此时我们最好将重载函数写入class中,变成inline或者加上domain,但如果你这样写,你在用的时候就不方便,比如重载后的操作符对象不能访问这个重载函数,不能访问重载函数那么就不能隐式的转换类型,此时我们要给inline的重载函数加上friend
关键字,使其变成友元函数