2014-05-05 28 views
2

我在C++中的一样预订了以下内容:超载基于L-值与R值

虽然我们不会在这本书中这样做,你可以重载一个 函数名(或经营)因此当使用 作为l值并将其用作r值时,它的行为会有所不同。 (请记住,l值意味着它可以在分配 语句的左侧使用。)例如,如果要函数f以 的行为不同,具体取决于它是否用作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; 
} 

有我错误地理解了吗?

+1

AFAIK函数重载不会因仅返回类型而有所不同 –

+1

@PaulRenton:不,但它们可以在常量上有所不同,如代码所示。 – rodrigo

回答

0

A const成员函数只能在const对象上调用。你对返回值做什么并没有什么不同。在你的例子中,f是非const的,所以它总是调用f()的非const版本。请注意,您也可以在C++ 11中重载r值引用(&&)。

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 ... 
}; 

有了这个代码,当调用其中sSomeClass类型的对象中,当s是非const第一版本将被调用,并且当sconst第二版本将被调用。价值类别与它无关。

参考资格如下:

#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" 
} 
1

Ofcourse这本书是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; 
} 

输出是

什么让你误会是函数签名。你看到当你有一个参数&arg(如id(&arg))时,你几乎预先定义了它的l值,所以通过const或非const成员函数返回它并不会改变事情。

作者引用了一种常见的写作风格,它允许'只要在const质量不同的签名声明'getters'和'setters',但仍编译和行为正确。

编辑

更迂腐,下列短语

回想的左值意味着它可以在一个赋值语句的左手侧使用。

已无效。 lr价值适用于表达式,最简单的解释方式是,我们可以采用的表达式是一个l值;如果无法获得,则为r值。

因此,作者引用的语法强制要在赋值运算符两侧正确使用成员函数(正确编译/重载解析)。这个现在不再与lr的价值有关。

+0

不,这本书是错误的,因为它将常量与lr值混合在一起。这些是不同的概念。也许在C++ 98中差异并不那么重要,但现在在C++ 11中是这样,因为现在你实际上可以重载一个对象的lr-value-ness,正如Brian的答案所示。 – rodrigo

+0

@rodrigo这是本书的背景,这个例子是常见的用例。从一个标准的观点来看,你是正确的,但是OP的用例是错误的,所以只需指出正确的用法。你认为这个[使用案例 - 见'x()'](http://content.gpwiki.org/index.php/C_plus_plus:Tutorials:TemplateVector)会在C++ 11开始时破坏代码吗? –

+0

我不明白为什么它会中断。这是一个标准的常量过载。 C++ 11大多是向后兼容的,所以我不会太担心。 – rodrigo