C++提供运算符重载主要目的:
- 希望对象之间的运算看起来可以和编译器内置类型一样丝滑;
- 相当于是告知编译器,类对象之间运算应该如何去做处理。
通过实现一个复数类,来阐述本文章的主题:
class Complex{
public:
Complex(int r = 1,int i = 1):real_(r),image_(i){}
~Complex(){}
void print(){
std::cout<<"real_= "<<real_<<std::endl;
std::cout<<"image_= "<<image_<<std::endl;
}
Complex operator+(const Complex&right){
return Complex(this->real_+right.real_,this->image_+right.image_);
}
private:
double real_;
double image_;
};
我们这里,为了满足Complex对象之间进行加法运算的需求,实现了Complex的加法运算符重载函数,看上去好像没有什么问题,我们使用一下该接口,挨个分析下面每个加法case:
int main(){
Complex com1(100,1000);
Complex com2(99,999);
Complex com3 = com1 + com2;
com3.print();
Complex com4 = com1 + 5;
com4.print();
return 0;
}
- Complex com3 = com1 + com2;
我们知道,运算符重载就相当于左边的对象调用自己的某个重载方法,将右边的值作为参数传递进去,这里也是一样的,相当于
com1.operator+(com2)
,这个样子,这样自然没有什么问题,比较经典的对象加法运算;
- Complex com4 = com1 + 5;
同样的,这里相当于com1.operator+(5)
,这里实际上发生了一个类型的强转,将int类型强转成了Complex类型,生成了一个临时的Complex对象初始化了形参,这个临时对象实际是Complex(5,1),因为该类的构造函数有默认值,所以可以只给一个参数生成临时对象,
最终,即com1.operator+(Complex(5,1))
,也没什么问题的,目前该运算符重载函数依然可以满足要求。
- Complex com5 = 6 + com1;
此时6在左边,编译器没有理由将6强转成Complex对象,因为此时不像上面第二个例子中的5一样,5作为实参传递给了Complex类型的形参,编译器找到了合适的构造函数才将5进行强转,然后初始化形参的。
此时,编译器发现没有能够满足该类加法的类内的运算符重载,所以就会在全局作用域内寻找:
Complex operator+(const Complex&left,const Complex&right){
return Complex(left.real_+right.real_,left.image_+left.image_);
}
此时, Complex com5 = 6 + com1;相当于left 为Complex(6,1)这样的临时对象,right为com1,由于全局作用域无法访问类内的私有变量,所以需要将此方法在类内生命为firend.
class Complex{
public:
Complex(int r = 1,int i = 1):real_(r),image_(i){}
~Complex(){}
void print(){
std::cout<<"real_= "<<real_<<std::endl;
std::cout<<"image_= "<<image_<<std::endl;
}
Complex operator+(const Complex&right){
return Complex(this->real_+right.real_,this->image_+right.image_);
}
friend Complex operator+(const Complex&left,const Complex&right);
private:
double real_;
double image_;
};
Complex operator+(const Complex&left,const Complex&right){
return Complex(left.real_+right.real_,left.image_+left.image_);
}
int main(){
Complex com1(100,1000);
Complex com2(99,999);
Complex com3 = com1 + com2;
com3.print();
Complex com4 = com1 + 5;
com4.print();
Complex com5 = 6 + com1;
com5.print();
return 0;
}
这里既提供了类内的运算符重载,也提供了全局的运算重载,编译器编译时,优先选择类内的,类内如果无法满足,就去全局找,如果全局都没法找到,那么就要编译报错了。
支持输入输出运算符重载:
我们知道我们经常使用的std::cout
和std::cin
实际上分别是ostream cout
和istream cin
对象
我们需要输出一个对象信息时,需要将我们需要输出的信息以一种格式交给ostream
对象
std::ostream& operator<<(std::ostream&out,const Complex&src){
out<<"real = "<<src.real_<<" image = "<<src.image_<<std::endl;
return out;
}
std::istream& operator>>(std::istream&in,Complex&src){
in >> src.real_ >> src.image_;
return in;
}
完整代码:
class Complex{
public:
Complex(int r = 1,int i = 1):real_(r),image_(i){}
~Complex(){}
void print(){
std::cout<<"real_= "<<real_<<std::endl;
std::cout<<"image_= "<<image_<<std::endl;
}
Complex& operator++(){
image_+=1;
real_+=1;
return *this;
}
Complex operator++(int){
return Complex(image_++,real_++);
}
Complex operator+(const Complex&right){
return Complex(this->real_+right.real_,this->image_+right.image_);
}
friend Complex operator+(const Complex&left,const Complex&right);
friend std::istream& operator>>(std::istream&in,Complex&src);
friend std::ostream& operator<<(std::ostream&out,const Complex&src);
private:
double real_;
double image_;
};
Complex operator+(const Complex&left,const Complex&right){
return Complex(left.real_+right.real_,left.image_+left.image_);
}
std::ostream& operator<<(std::ostream&out,const Complex&src){
out<<"real = "<<src.real_<<" image = "<<src.image_<<std::endl;
return out;
}
std::istream& operator>>(std::istream&in,Complex&src){
in >> src.real_ >> src.image_;
return in;
}
int main(){
Complex com1(100,1000);
Complex com2(99,999);
Complex com3 = com1 + com2;
com3.print();
Complex com4 = com1 + 5;
com4.print();
Complex com5 = 6 + com1;
com5.print();
std::cout<<com5;
std::cin>>com5;
std::cout<<com5;
return 0;
}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)