我正在制作一个复数类,以便重载运算符。
#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);
答案 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)