在函数声明结束时使用“const”重载

时间:2015-08-20 16:57:50

标签: c++ c++11 overload-resolution

我有3次尝试重载函数“begin()”

class Test
{
public:

    //case 1: compiler error
    int begin();
    const int begin();

    //case 2:compiler warning: type qualifiers ignored on function return type
    int begin();
    const int begin() const;

    //case 3: ok
    int begin();
    int begin() const;
};

对于成功构建的两种情况,编译器如何选择为begin()调用哪个重载?

3 个答案:

答案 0 :(得分:4)

成员函数有一个隐式参数,它是类本身的实例。所以你可以认为你的功能看起来很像:

// 1) compile-error as const-qualifications on return doesn't distinguish
//    the functions - you cannot overload on return type
int begin(Test& );
const int begin(Test& );

// 2)
int begin(Test& );
const int begin(const Test& );

// 3)
int begin(Test& );
int begin(const Test& );

对于第二和第三种情况,函数的const - 限定等同于隐式参数是对const的引用。所以当你有类似的东西时:

Test{}.begin();

使用对非const begin()的引用作为隐式的第一个参数调用Testbegin()的两个重载都是可行的,都不需要转换,所以最少 cv - 限定引用,这是非const限定函数。

相反,当你有:

(const Test{}).begin();

我们通过引用begin()致电const Test。所以非const - 限定函数不是一个可行的候选函数(你不能将const-ref传递给期望非const-ref的函数),所以最好的可行候选者是唯一可行的候选者:{{ 1}}。

答案 1 :(得分:3)

案例1不明确因为返回类型不参与重载决策, 情况2等同于情况3,因为const在返回类型中被丢弃 在案例3中:

const Test t1;
t1.begin() // calls int begin() const;
Test t2;
t2.begin() // calls int begin();

来自cppreference.com

  

非静态成员函数可以用const,volatile声明,   或const const限定符(此限定符出现在名称后面。)   函数声明中的函数)。不同的cv资格   函数有不同的类型,因此可能会相互重载。在里面   一个cv限定函数的主体,这个指针是cv限定的,   例如在const成员函数中,只有其他const成员函数可以   通常被称为。 (仍然可以调用非const成员函数   如果应用const_cast或通过不访问路径   涉及这个。)

答案 2 :(得分:2)

要记住一些规则:

  1. 您不能仅基于返回类型重载方法。这会导致案例1中的错误。

  2. 按值返回时,const限定符是多余的。在您的情况2中,编译器会向您发出警告。

  3. 该类的每个非静态方法都有一个隐式参数。在方法调用上,将其分配给调用该方法的实例。方法声明结束时(方法体之前)的const关键字适用于此隐式参数。你基本上说的是函数的主体不会修改实例的状态(数据成员)。如果在const实例上调用该方法,则需要定义const方法。此外,您可以仅根据是否为const来重载该方法。