为啥不调用具有 const 引用返回值的重载方法?

Posted

技术标签:

【中文标题】为啥不调用具有 const 引用返回值的重载方法?【英文标题】:Why the overloaded method with const reference return value is not called?为什么不调用具有 const 引用返回值的重载方法? 【发布时间】:2017-09-29 18:31:13 【问题描述】:

考虑以下代码:

#include <iostream>

using namespace std;

class A 
    private:
    int x;
    public:
    int& get_ref() 
        cerr << "non const" << endl;
        return x;
    

    const int& get_ref() const 
        cerr << "const" << endl;
        return x;
    
;

int main () 
    A a;
    a.get_ref() = 10;

    cout << a.get_ref() << endl;

    const int& y = a.get_ref();

    return 0;

我希望对a.get_ref() 的第二次和第三次调用运行get_ref() 方法的第二个版本(并在标准错误上输出const)。但看起来总是第一个版本被调用。如何实现两个不同的“getter”并确保根据上下文调用正确的版本?即,至少在第三次通话中

const int& y = a.get_ref();

第二个版本执行了吗? (不优雅的解决方案是使用不同的名称,例如 get_refget_const_ref,但我想看看是否可以避免这种情况。)

【问题讨论】:

【参考方案1】:

重载解析不依赖于返回值,而只依赖于参数,包括要为成员函数调用的对象。 a 是一个非常量对象,那么对于a.get_ref(),将一直调用非常量成员函数。

您可以将其转换为 const 以调用 const 版本:

const_cast<const A&>(a).get_ref();

顺便说一句:给他们起不同的名字并不是一个坏主意。这就是我们在 STL 中使用 std::cbeginstd::cend 的原因。

【讨论】:

感谢您的澄清!因此,这尤其意味着从类内部对get_ref 的任何调用都将被解析为第一个(非常量)版本(除非我们将this 转换为const,类似于您的建议)。我说的对吗? @PBM 更准确地说,任何从类的成员函数调用get_ref,解析取决于this指向constnon-const,即被调用的成员函数首先是const。所以在const成员函数内部,当调用get_ref时,会调用const get_ref;在非常量成员函数中,将调用非常量get_ref【参考方案2】:

重载决议只关心调用的参数(包括this 的隐式参数)。表达式a.get_ref() 必须计算为相同的重载,而不管其返回值会发生什么。这是 C++ 的基础,您对此无能为力。

如果要调用const-qualified 版本,请使用const-qualified 对象表达式:

const int& y = const_cast<const A&>(a).get_ref();

【讨论】:

根据您要处理的具体情况,当然有可能的解决方法。如果你指定为什么你想要这样的行为,我可能会想出一个解决方法。这将是丑陋和令人沮丧的,但可能是可能的。

以上是关于为啥不调用具有 const 引用返回值的重载方法?的主要内容,如果未能解决你的问题,请参考以下文章

c++中为啥赋值运算符重载返回类型是引用

c++中重载输出操作符,为啥要返回引用

为啥我们在赋值运算符重载中使用引用返回而不是在加减运算中?

为啥 const 方法不能返回非常量引用?

当它绑定到调用函数中的 const 引用时,它的返回值的生命周期如何扩展到调用函数的范围?

当它被绑定到调用函数中的const引用时,它的返回值的生命周期如何扩展到调用函数的范围?