运营商LT;<超载。无法直接在cout中直接使用另一个重载运算符的结果

时间:2018-03-19 06:50:50

标签: c++ operator-overloading

我正在制作一个复数类,以便重载运算符。

#include <iostream>
class Complex
{
    double real;
    double imaginary;

public:

    Complex(double real, double imaginary) : real(real), imaginary(imaginary) {}
    ~Complex() = default;

    friend std::ostream &operator<<(std::ostream &out, Complex &source)
    {
        out << "(" << source.real << " + " << source.imaginary << ")";
        return out;
    }

    friend Complex operator+(const Complex &a, const Complex &b)
    {
        return Complex(a.real + b.real, a.imaginary + b.imaginary);
    }

};

int main()
{
    Complex c1(3, 2.25);
    Complex c2(2.25, 3);
    Complex res = c1 + c2;

    std::cout << res;
    return 0;
}

类定义没有完成,因为我需要更多地重载一些运算符。但是,如果我编译并运行项目,我会按预期在屏幕上打印结果,但如果我不使用结果变量来打印cout cout<< c1+c2;我会收到以下错误:

error: no match for 'operator<<' (operand types are 'std::ostream {aka std::basic_ostream<char>}' and 'cmp::Complex')

如果我尝试使用cout<< &(c1+c2);,我会收到错误消息:

error: taking address of temporary [-fpermissive]

并不是我打算这样写的。

我的印象是它失败了,因为c1 + c2不作为参考,因为它是一个临时对象,没有保存在任何地方,因为我根据第二个错误不能引用临时对象,它失败。这就解释了为什么当我在结果上保存c1 + c2的结果时,我可以毫无错误地执行程序。

在我正在观看的视频中,使用了Eclipse,在我的情况下,我正在使用带有GNU GCC编译器的Codeblocks。

你能帮我理解我做错了什么吗?为什么它不适用于我的情况,但在视频上使用相同的语法?

编辑: 解决方案:&lt;&lt; operator函数应该采用Complex类型的const引用。临时对象只能绑定到const引用。因此它的原型应该看起来像这样...

friend ostream &operator<<(ostream &out,const Complex &source);

2 个答案:

答案 0 :(得分:2)

c1+c2生成一个临时对象,这不能绑定到流运算符中的非const引用。您需要将其更改为const引用

答案 1 :(得分:1)

问题:

...
friend ostream &operator<<(ostream &out,Complex &source);
...
cout<< c1+c2; // error or warning
...

为什么不工作?

c1+c2的表达式评估prvalue的临时对象。

std::cout<<c1+c2;正试图将prvalue绑定到左值引用

  

所有临时对象都被销毁,作为评估的最后一步   表达式(词法上)包含它们所在的点   创建,如果创建了多个临时对象,它们就是   按照与创造顺序相反的顺序销毁。这是真的   即使该评估以抛出异常而告终。

解决方案?

  

临时对象的生命周期可以通过绑定到a来扩展   const左值引用或右值引用(自C ++ 11起)

...
//  using rvalue reference
friend std::ostream &operator<<(std::ostream &out, Complex &&source)
{
    source.real += 100; // non const value in function signature allows us to modify 'source'
    out << "(" << source.real << " + " << source.imaginary << ")";
    return out;
}
...

const限定符添加到函数参数:

...
// using const lvalue reference
friend std::ostream &operator<<(std::ostream &out, const Complex &source)
{
    out << "(" << source.real << " + " << source.imaginary << ")";
    return out;
}
...

如果我们同时拥有所有这些重载怎么办?

  

当用作函数参数和两个重载时   功能可用,一个采用右值参考参数和   其他采用左值引用const参数,rvalue绑定到   rvalue引用重载(因此,如果同时复制和移动   构造函数可用,rvalue参数调用移动   构造函数,同样具有复制和移动赋值运算符)。

实施例

#include ...

int main()
{
    Complex c1(3, 2.25);
    Complex c2(2.25, 3);

    auto lvalue = c1 + c2;
    auto && rlvalueRef = c1 + c2;
    const auto& constlvalueRef = c1 + c2;
    const auto constlvalue = c1 + c2;

    std::cout
        << constlvalue
        << lvalue
        << rlvalueRef
        << constlvalueRef
        << c1 + c2
        << std::endl;

    return 0;
}

输出:

non modified: (5.25 + 5.25)
non modified: (5.25 + 5.25)
non modified: (5.25 + 5.25)
non modified: (5.25 + 5.25)
modified output: (105.25 + 5.25)