函数重载常见问题

文章讨论了C++编程中遇到的两个问题。第一个问题是关于尝试将右值传递给非常量左值引用,导致编译错误。解决方案是将函数参数改为常量引用或使用临时变量。第二个问题涉及运算符重载,特别是+运算符返回引用,这可能导致临时对象的问题。修正方法是改变+运算符的返回类型,避免返回引用,同时更新输出运算符重载以接受const引用。
摘要由CSDN通过智能技术生成

 问题一

cannot bind non-const lvalue reference of type 'Complex&' to an rvalue of type 'Complex'

该错误提示出现的原因是,代码在进行函数调用或赋值等操作时,将一个临时对象(也称为右值)传递给了一个非常量左值引用类型的参数。对于这种情况,C++语言标准禁止这样的操作,因为非常量左值引用只能绑定到左值,而无法绑定到右值。 

例如:

void setComplex(Complex& comp) {
    // do something
}

int main() {
    setComplex(Complex(1.0, 2.0)); // Error!
    return 0; 
}

这里在调用setComplex函数时,使用了一个右值Complex(1.0, 2.0)作为实参,并试图将其绑定到一个非常量左值引用Complex& comp上,从而导致了编译错误。

解决这个问题的方法可以有两种:

  1. 将函数参数改为常量引用类型const Complex& comp,以使其可以接受右值参数。
  2. 将实参转换成左值后再传递给函数参数。例如,可以将一个临时对象的值复制给一个命名变量,然后将该变量的引用传递给函数。

解决方式:

void setComplex(const Complex& comp) {
    // do something
}

int main() {
    Complex c(1.0, 2.0);
    setComplex(c); // OK
    setComplex(Complex(1.0, 2.0)); // OK
    return 0; 
}

问题二

运算符重载两个类cout与相加,而A+B不能直接用cout输出,还需要中间变量将A+B存下来再输出

#include<iostream>
using namespace std;

class Complex{
private:
    double real;//实部
    double image;//虚部

public:
    //友元函数重载输入输出运算符
    friend ostream& operator <<(ostream &os,Complex &com);
    friend istream& operator>>(istream&is,Complex &com);
    friend Complex &operator+(Complex &A,Complex &B);
    friend Complex &operator-(Complex &A,Complex &B);
    friend Complex &operator*(Complex &A,Complex &B);
    friend Complex &operator/(Complex &A,Complex &B);
    
    Complex(double a,double b){
        real = a;
        image = b;
    }
    Complex(){}
};

ostream& operator <<(ostream &os,Complex &com){
    if(com.image>=0) os<<com.real<<"+"<<com.image<<"i"<<endl;
    else os<<com.real<<com.image<<"i"<<endl;
    return os;
}

istream& operator>>(istream&is,Complex &com){
    return is>>com.real>>com.image;
}

Complex &operator+(Complex &A,Complex &B){
    Complex C;
    C.real = A.real+B.real;
    C.image = A.image+B.image;
    return C;
}
Complex &operator-(Complex &A,Complex &B){
    Complex C;
    C.real = A.real-B.real;
    C.image = A.image-B.image;
    return C;
}
Complex &operator*(Complex &A,Complex &B){
    //ac-bd (ad+bc)i
    Complex C;
    C.real = A.real*B.real-A.image*B.image;
    C.image = A.real*B.image+A.image*B.real;
    return C;
}
Complex &operator/(Complex &A,Complex &B){
    Complex C;
    C.real = A.real*B.real+A.image*B.image/(B.image*B.image+B.real*B.real);
    C.image = (A.image*B.real-A.real*B.image)/(B.image*B.image+B.real*B.real);
    return C;
}

int main()
{
    Complex A,B;
    cin>>A>>B;
    cout<<"A:"<<A<<endl;
    cout<<"B:"<<B<<endl;
    cout<<"A+B:"<<A+B<<endl;
    cout<<"A-B:"<<A-B<<endl;
    cout<<"A*B:"<<A*B<<endl;
    cout<<"A/B:"<<A/B<<endl;

}

 以上代码编译时会CE,原因是:

1.在实现operator+函数时,返回了一个Complex类型的引用,但是没有定义对应的构造函数。因此,在进行类似于A + B这样的运算时,返回的对象类型并不是原先的Complex类型,而是一组新的数据。当试图使用这些数据时可能会发生不可预料的错误。

此外,由于operator+中返回的是一个临时创建的对象,该对象只能存活到表达式结束位置。所以如果直接将其作为参数传递给输出流,其所保存的信息在输出时可能已经不存在了,从而导致输出结果出错。

为了解决这个问题,应将operator+函数的返回值类型改为Complex类型(非引用类型),然后将计算的结果暂存到新的Complex类型变量中再返回。

2.在operator<<重载函数中,第二个参数应该是const类型的引用const Complex& com。因为输出运算符不应该修改对象的状态。

在使用<<操作符时,左操作数必须是一个输出流对象,但此处将Complex对象作为了左操作数。应该将输出流和Complex对象通过流插入操作符<<连接起来,将其放在右侧,才能完成输出操作。比如可以像下面这样实现overload <<运算符的实现:

修正后的代码:

#include<iostream>
using namespace std;

class Complex{
private:
    double real;//实部
    double image;//虚部

public:
    //友元函数重载输入输出运算符
    friend ostream& operator<<(ostream &os,const Complex &com);
    friend istream& operator>>(istream&is,Complex &com);
    friend Complex operator+(Complex &A,Complex &B);
    friend Complex operator-(Complex &A,Complex &B);
    friend Complex operator*(Complex &A,Complex &B);
    friend Complex operator/(Complex &A,Complex &B);
    
    Complex(double a,double b){
        real = a;
        image = b;
    }
    Complex(){}
};

ostream& operator <<(ostream &os,const Complex &com){
    if(com.image>=0) os<<com.real<<"+"<<com.image<<"i"<<endl;
    else os<<com.real<<com.image<<"i"<<endl;
    return os;
}

istream& operator>>(istream&is,Complex &com){
    return is>>com.real>>com.image;
}

Complex operator+(Complex &A,Complex &B){
    Complex C;
    C.real = A.real+B.real;
    C.image = A.image+B.image;
    return C;
}
Complex operator-(Complex &A,Complex &B){
    Complex C;
    C.real = A.real-B.real;
    C.image = A.image-B.image;
    return C;
}
Complex operator*(Complex &A,Complex &B){
    //ac-bd (ad+bc)i
    Complex C;
    C.real = A.real*B.real-A.image*B.image;
    C.image = A.real*B.image+A.image*B.real;
    return C;
}
Complex operator/(Complex &A,Complex &B){
    Complex C;
    C.real = A.real*B.real+A.image*B.image/(B.image*B.image+B.real*B.real);
    C.image = (A.image*B.real-A.real*B.image)/(B.image*B.image+B.real*B.real);
    return C;
}

int main()
{
    Complex A,B;
    cin>>A>>B;
    cout<<"A:"<<A;
    cout<<"B:"<<B;
    cout<<"A+B:"<<A+B;
    cout<<"A-B:"<<A-B;
    cout<<"A*B:"<<A*B;
    cout<<"A/B:"<<A/B;

}

运行结果

1 2
1 -2
A:1+2i
B:1-2i
A+B:2+0i
A-B:0+4i
A*B:5+0i
A/B:0.2+0.8i

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值