我在C ++书中发现了以下内容:
虽然我们不会在本书中这样做,但你可以重载一个 函数名称(或运算符),以便在使用时表现不同 作为l值并且当它用作r值时。 (回想一下 l值意味着它可以在赋值的左侧使用 声明。)例如,如果你想要一个函数f来表现 取决于它是用作l值还是用作l值 r值,你可以这样做:
class SomeClass {
public:
int& f(); // will be used in any l-value invocation const
const int& f( ) const; // used in any r-value invocation ...
};
我尝试过这个并没有用:
class Foo {
public:
int& id(int& a);
const int& id(int& a) const;
};
int main() {
int a;
Foo f;
f.id(a) = 2;
a = f.id(a);
cout << f.id(a) << endl;
}
int& Foo :: id(int& a) {
cout << "Bar\n";
return a;
}
const int& Foo :: id(int& a) const {
cout << "No bar !\n";
return a;
}
我是否错误地理解了它?
答案 0 :(得分:3)
这本书的例子都是错误的,或者你从书中复制了错误的例子。
class SomeClass {
public:
int& f(); // will be used in any l-value invocation const
const int& f( ) const; // used in any r-value invocation ...
};
使用此代码,当您致电s.f()
,其中s
是SomeClass
类型的对象时,s
为非{{1}时将调用第一个版本当const
为s
时,将调用第二个版本。价值类别与它无关。
参考资格如下:
const
答案 1 :(得分:1)
当然这本书是correct。让我解释作者的意思的一个例子的工作原理:
#include <iostream>
using namespace std;
class CO
{
int _m;
public:
CO(int m) : _m(m) {}
int& m() { return _m; } // used as an l-value
int const& m() const { return _m; } // used as an r-value
};
int main()
{
CO a(1);
cout << a.m() << endl;
a.m() = 2; // here used as an l-value / overload resolution selects the correct one
cout << a.m() << endl;
return 0;
}
输出
1
2
你误解的是功能签名。你看到你有一个参数&arg
(如在id(&arg)
中)你几乎预定了它的l-valuness,所以通过const或非const成员函数返回它不会改变一个东西。 / p>
作者提到了一种通用的写作风格,允许“吸气者”。和&#39;塞特斯&#39;使用仅在const
限定符中签名的签名进行声明,但编译和行为正确。
修改强>
更迂腐,以下短语
回想一下l值意味着它可以在赋值语句的左侧使用。
不再有效。 lr 评价适用于表达式,最简单的解释方法是,我们可以采用的表达式是一个l值;如果它不可获得它是一个r值。
因此作者引用的语法强制在赋值运算符的两侧正确使用成员函数(正确的编译/重载解析)。现在这与 lr 价值不再相关。
答案 2 :(得分:0)
只能在const对象上调用const
成员函数。您对返回值的处理方式没有区别。在您的示例中,f是非const,因此它始终调用f()
的非const版本。请注意,您还可以在C ++ 11中重载r值引用(&&
)。