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、 eA运算符+(常数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”)
),这可能会导致动态内存分配和删除,从而导致严重的运行时成本。哦,我只是觉得这样会更方便,而且不那么多余。但是,如果它真的造成了一些严重的运行时成本,那么我想你有道理。谢谢,谢谢你的解释。我知道上面不是实现操作符的最佳方法,但我只是想知道为什么编译器会在上面的代码中抱怨。