首页 > 解决方案 > 像“>>,<<”这样的运算符重载不起作用

问题描述

这是我的代码

#include<iostream>
using namespace std;
class Complex
{
private:
    double re;
    double im;
public:
    Complex(double x=0,double y=0):re(x),im(y){}
    friend ostream& operator<<(ostream&os,const Complex&a);
    friend istream& operator>>(istream &is,const Complex&a);
};
ostream& operator<<(ostream&os,const Complex&a)
{
    os<<"a"<<a.re<<"+j"<<a.im<<endl;
    return os;
}
istream& operator>>(istream&is,const Complex&a)
{
    is>>a.re>>a.im;
    return is;
}
int main()
{
    Complex d;
    cout<<"enter the value of object";
    cin>>d;
    cout<<"value is"<<d;
    return 0;
}

当我执行程序运行并自动停止时,它给出以下输出

进程返回 -1073741571 (0xC00000FD) 执行时间:3.066 s 按任意键继续。

标签: c++

解决方案


主要问题是您将operator>> const. const引用不能用于修改对象,但应该operator>>这样做。

现在,问题是,它为什么要编译?期望是没有可行的重载operator>>将 a const double&(重载的类型a.rea.im在您的operator>>重载中)作为第二个参数。标准库中只有一个double&重载。那么如何不is>>a.re>>a.im;导致编译失败呢?

那是因为您使用 type 的一个参数创建了Complexnon-explicit和 callable的构造函数double

因此每个>>

is>>a.re>>a.im;

实际上将operator>>再次调用您的重载,通过使用提到的非构造函数将a.reora.im参数从doubleto进行用户定义的转换,并且可以再次绑定到的引用。ComplexexplicitComplexconstoperator>>

explicit如果您没有任何特定理由,您应该创建可以默认使用一个参数调用的构造函数,以避免此类问题。关键字禁止在上述explicit隐式转换序列中使用构造函数,这通常是令人惊讶和无意的。

因此,您可以有效地进行无限递归operator>>(如果您启用警告,您的编译器可能会告诉您这一点)。这在理论上会导致未定义的行为,并且在实践中会导致堆栈溢出导致分段错误。


推荐阅读