我有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()
调用哪个重载?
答案 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()
的引用作为隐式的第一个参数调用Test
。 begin()
的两个重载都是可行的,都不需要转换,所以最少 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();
非静态成员函数可以用const,volatile声明, 或const const限定符(此限定符出现在名称后面。) 函数声明中的函数)。不同的cv资格 函数有不同的类型,因此可能会相互重载。在里面 一个cv限定函数的主体,这个指针是cv限定的, 例如在const成员函数中,只有其他const成员函数可以 通常被称为。 (仍然可以调用非const成员函数 如果应用const_cast或通过不访问路径 涉及这个。)
答案 2 :(得分:2)
要记住一些规则:
您不能仅基于返回类型重载方法。这会导致案例1中的错误。
按值返回时,const限定符是多余的。在您的情况2中,编译器会向您发出警告。
该类的每个非静态方法都有一个隐式参数。在方法调用上,将其分配给调用该方法的实例。方法声明结束时(方法体之前)的const关键字适用于此隐式参数。你基本上说的是函数的主体不会修改实例的状态(数据成员)。如果在const实例上调用该方法,则需要定义const方法。此外,您可以仅根据是否为const来重载该方法。