Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/160.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 关于重载运算符的问题+;_C++_Operator Overloading - Fatal编程技术网

C++ 关于重载运算符的问题+;

C++ 关于重载运算符的问题+;,c++,operator-overloading,C++,Operator Overloading,考虑以下代码: class A { public: A& operator=( const A& ); const A& operator+( const A& ); const A& operator+( int m ); }; int main() { A a; a = ( a + a ) + 5; // error: binary '+' : no operator found which takes a left-hand operand

考虑以下代码:


class A
{
public:
    A& operator=( const A& );
    const A& operator+( const A& );
    const A& operator+( int m );
};

int main()
{
    A a;
    a = ( a + a ) + 5;   // error: binary '+' : no operator found which takes a left-hand operand of type 'const A'
}
有人能解释为什么上面的内容会作为错误返回吗

(a+a)
”调用“
常量a和运算符+(常量a&)
”,并返回一个常量引用,如果我没有弄错的话,该常量引用随后被传递到“
常量a和运算符+(int m)


如何修复上述错误(不创建全局二进制运算符+或接受int的构造函数),从而允许
main()
中的语句?

operator+
应返回实例,而不是引用:

// as member function
A operator+(const A& other);

// as free function
A operator+(const A& left, const A& right);
解释具体问题的方法是“返回一个常量引用,然后将其传递给
常量a&operator+(int m)
”。由于您有一个const引用,它无法调用该函数,因为它不是const方法(即
const a&operator+(int m)const

也就是说,这不是修复
操作符+
的方法。如果您要返回一个引用,它是指向什么的引用?local in运算符+将不好,因为您不应该返回对local的引用。对全局的引用是不好的,因为它会限制代码的正确使用。对已分配内存的引用将是错误的,因为它将泄漏内存。对
*的引用将是不好的,因为
操作符+
的行为就像
操作符+=

如果我没弄错的话,它会被传递到“const A&operator+(int m)”

不可以。因为LHS是一个
常量a&
,而RHS是一个
int
,它将调用*

[anyType] operator+ (int rhs) const
//                            ^^^^^ note the const here.
由于您只提供了非
const
版本
const A&operator+(int m)
,编译器会抱怨

*:或
operator+(const int&rhs)const
operator+(float rhs)const
。。。关键的一点是它必须是一个
const
方法。

问题是
(a+a)
返回一个所谓的右值(基本上是临时值的一个奇特术语)。虽然可以在右值上调用成员函数,但只能调用
const
成员函数。此外,每个人都正确地说,
操作符+
必须始终返回一个新值

您的运算符应按以下方式实现:

A operator+( const A& ) const;
A operator+( int m ) const;
但是,不修改其左参数的二进制运算符可能更好地实现为自由函数:

class A { ... };

A operator+(const A& lhs, const A& rhs);
A operator+(const A& lhs, int rhs);
通常,它们是在
操作符+=
之上实现的,后者是作为成员实现的:

class A {
  public:
   A& operator+=(const A& rhs);
   A& operator+=(int rhs);
};

inline A operator+(A lhs, const A& rhs) // note: lhs is passed by copy now
{
  lhs += rhs;
  return lhs;
}
A operator+(A lhs, int rhs) // note: lhs is passed by copy now
{
  lhs += rhs;
  return lhs;
}

因为添加时正在修改左侧对象。对于
const
对象,不能这样做。顺便说一句,请接受Samuel的建议,因为惯用的方法是返回添加对象的新副本。

函数需要常量:


const A&operator+(int m)const

作为
常量A和运算符+(常量A&)
返回常量引用。非常量成员函数
常量A和运算符+(int m)
不能通过常量对象调用。 第一个运算符应定义为
A&operator+(const A&)
,或者第二个运算符应定义为
const A&operator+(int m)const
; 然而,这些更改只会使它们在技术上正确,在大多数情况下不会美观,因为二进制运算符不应该修改任何输入参数,也不应该计算结果和返回。因此,结果必须通过值返回,或者在C++0x的情况下,作为r值引用返回。
i、 e
A运算符+(常数A和rhs)常数
A和运算符+(常数A和rhs)常数

@R塞缪尔:是的,我明白。我从考试中拿出来的,这就是为什么我没有改变它。@jasonline:如果你真的在考试中拿了这个,那么,如果你能,就放弃考试吧。这段代码几乎和你能做的一样糟糕,我认为没有什么空间让它变得更糟。@AraK:是的,我知道它应该返回一个新对象。这段代码是从考试中提取的,所以我没有费心修改它。@jasonline:你确定考试没有以这种方式实现
+=
?很难想象任何考试都会出错。@sbi:我想考试只是想测试我是否能确定是哪个部分导致了错误。不是真的想用正确的方法实现它。@sbi:谢谢你提供的信息,是的,我知道最好的实现方法是作为一个全局函数,并添加一个使用int进行转换的构造函数。我只是不理解const部分,这就是为什么。@jasonline:最好的方法通常是不要使用隐式cast构造函数,因为这需要从
int
创建一个临时
a
。通常,最好的方法是为
int
定义不同的运算符重载,这样可以避免创建临时变量。(如果构造函数很简单,并且所有涉及的代码都是内联的,编译器可能能够消除临时性的。)您的意思是定义两个重载运算符,其中int在lhs上,而int在rhs上?但在这种情况下,创建临时文件有什么不好呢?@jasonline:是的,这就是我的意思。对于你的
A
,临时或不临时可能不会有太大的区别。但是想想
std::string
:如果为了将字符串文字附加到字符串(
s1+“blah”
)中,必须首先将文字转换为
std::string
(基本上是
s1+std::string(“blah”)
),这可能会导致动态内存分配和删除,从而导致严重的运行时成本。哦,我只是觉得这样会更方便,而且不那么多余。但是,如果它真的造成了一些严重的运行时成本,那么我想你有道理。谢谢,谢谢你的解释。我知道上面不是实现操作符的最佳方法,但我只是想知道为什么编译器会在上面的代码中抱怨。