请考虑以下代码:
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 )
”调用“const A& operator+( const A& )
”并返回一个常量引用,如果我没记错,则会将其传递给“const A& operator+( int m )
”。
如何修复上述错误(不创建全局二元运算符+或接受int的构造函数),以便允许main()
内的语句?
答案 0 :(得分:7)
然后传递给“const A& operator +(int m)”如果我没弄错的话
没有。由于LHS是const 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
方法。
答案 1 :(得分:6)
operator+
应该返回一个实例,而不是引用:
// as member function
A operator+(const A& other);
// as free function
A operator+(const A& left, const A& right);
解释具体问题是“返回一个常量引用,然后传递给const A& operator+( int m )
”。由于你有一个const引用,它不能调用该函数,因为它不是const方法(即const A& operator+( int m ) const
)。
那就是说,这不是修复operator+
的方法。如果你要返回一个引用,它的引用是什么?运算符+中的本地会很糟糕,因为您不应该返回对本地的引用。对全局的引用会很糟糕,因为它会限制代码的正确使用方式。对分配的内存的引用会很糟糕,因为它会泄漏内存。对*this
的引用会很糟糕,因为operator+
的行为与operator +=
相似。
答案 2 :(得分:2)
因为您在添加时正在修改左侧对象。你不能用const
对象做到这一点。以Samuel建议为例,因为惯用的方法是返回添加对象的新副本。
答案 3 :(得分:1)
问题是(a+a)
会返回一个所谓的 rvalue (基本上是一个临时的花哨术语)。虽然可以在rvalue上调用成员函数,但只能调用const
成员函数。此外,每个人都说operator+
必须返回一个新值。
您的运营商应该像这样实施:
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);
通常,它们是在operator+=
之上实现的,它是作为成员实现的:
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;
}
答案 4 :(得分:1)
该函数需要为const:
const A& operator+( int m ) const;
答案 5 :(得分:1)
当const A& operator+( const A& )
返回一个const引用时,不能通过const对象调用非const成员函数const A& operator+( int m )
。
或者,第一个运算符应定义为A& operator+( const A& )
,或第二个运算符定义为const A& operator+( int m )const
;
但是,这些更改只会使它们在技术上正确,在大多数情况下不会在美学上,因为二元运算符不应该修改任何输入参数,而是计算结果并返回。因此,结果必须通过值返回,或者在C ++ 0x的情况下,作为r值引用。
即A operator+(const A& rhs)const
或A&& operator+(const A& rhs)const
;