[英]Overloading Based on L-Value versus R-Value
我在一本书中发现以下内容:
尽管我们不会在本书中进行介绍,但是您可以重载函数名称(或运算符),以使其在用作l值和用作r值时表现不同。 (回想一下,l值意味着可以在赋值语句的左侧使用它。)例如,如果您希望函数f的行为不同,这取决于将其用作l值还是r -value,您可以按照以下步骤操作:
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;
}
我误会了吗?
本书的例子完全是错误的,或者您从本书中复制了错误的例子。
class SomeClass {
public:
int& f(); // will be used in any l-value invocation const
const int& f( ) const; // used in any r-value invocation ...
};
使用此代码,当您调用sf()
,其中s
是SomeClass
类型的对象,当s
为非const
时将调用第一个版本,而当s
为const
时将调用第二个版本。 值类别与此无关。
Ref资格看起来像这样:
#include <iostream>
class SomeClass {
public:
int f() & { std::cout << "lvalue\n"; }
int f() && { std::cout << "rvalue\n"; }
};
int main() {
SomeClass s; s.f(); // prints "lvalue"
SomeClass{}.f(); // prints "rvalue"
}
当然这本书是正确的 。 让我解释一个作者的例子的工作原理:
#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值,因此通过const或非const成员函数返回它不会改变任何事情。
作者指的是一种通用的书写样式,该样式允许声明“ getters”和“ setters”时使用的签名仅在const
限定词中有所不同, 但可以正确编译和运行。
编辑
为了更加学究,以下短语
回想一下,l值意味着可以在赋值语句的左侧使用它。
不再有效。 lr值适用于表达式,最简单的解释方法是,我们可以取其地址的表达式为l值; 如果无法获得,则为r值。
因此,作者所引用的语法将强制成员函数在赋值运算符的两侧正确使用(正确的编译/重载解析)。 如今,这与lr的价值不再相关。
const
成员函数只能在const对象上调用。 对返回值所做的操作没有任何区别。 在您的示例中,f是非常量的,因此它始终调用f()
的非常量版本。 请注意,您还可以在C ++ 11中重载r值引用( &&
)。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.