在函数声明末尾使用“const”重载
Overloading with “const” at end of function declaration
我有 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()
调用哪个重载?
情况 1 不明确,因为 return 类型不参与重载决议,
case 2 等同于 case 3 因为 const 在 return 类型中被丢弃
案例3:
const Test t1;
t1.begin() // calls int begin() const;
Test t2;
t2.begin() // calls int begin();
A non-static member function can be declared with a const, volatile,
or const volatile qualifier (this qualifier appears after the name of
the function in function declaration). Differently cv-qualified
functions have different types and so may overload each other. In the
body of a cv-qualified function, the this pointer is cv-qualified,
e.g. in a const member function, only other const member functions may
be called normally. (A non-const member function may still be called
if const_cast is applied or through an access path that does not
involve this.)
成员函数有一个隐式参数,它是 class 本身的实例。所以你可以认为你的函数看起来像:
// 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
限定等同于隐式参数是对常量的引用。所以当你有类似的东西时:
Test{}.begin();
调用 begin()
使用对非常量 Test
的引用作为隐式第一个参数。 begin()
的两个重载都是可行的,都不需要转换,因此首选最少 cv 限定的引用,即非 const
限定的函数。
相反,当您拥有:
(const Test{}).begin();
我们正在调用 begin()
并引用 const Test
。所以非 const
限定的函数不是一个可行的候选者(你不能将 const-ref 传递给期望非 const-ref 的函数),所以最好的可行候选者是唯一可行的候选者:int begin() const
。
要记住的几条规则:
不能仅基于 return 类型重载方法。这会导致您的案例 1 中出现错误。
当按值 returning 时,const 限定符是多余的。在你的情况 2 中,编译器警告你这一点。
class 的每个非静态方法都有一个隐式参数。在方法调用时,this 被分配给调用该方法的实例。方法声明末尾(方法体之前)的 const 关键字适用于此隐式参数。您实质上是在说函数体不会修改实例的状态(数据成员)。如果在 const 实例上调用该方法,则需要定义 const 方法。此外,您可以仅根据是否为 const 的事实来重载该方法。
我有 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()
调用哪个重载?
情况 1 不明确,因为 return 类型不参与重载决议, case 2 等同于 case 3 因为 const 在 return 类型中被丢弃 案例3:
const Test t1;
t1.begin() // calls int begin() const;
Test t2;
t2.begin() // calls int begin();
A non-static member function can be declared with a const, volatile, or const volatile qualifier (this qualifier appears after the name of the function in function declaration). Differently cv-qualified functions have different types and so may overload each other. In the body of a cv-qualified function, the this pointer is cv-qualified, e.g. in a const member function, only other const member functions may be called normally. (A non-const member function may still be called if const_cast is applied or through an access path that does not involve this.)
成员函数有一个隐式参数,它是 class 本身的实例。所以你可以认为你的函数看起来像:
// 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
限定等同于隐式参数是对常量的引用。所以当你有类似的东西时:
Test{}.begin();
调用 begin()
使用对非常量 Test
的引用作为隐式第一个参数。 begin()
的两个重载都是可行的,都不需要转换,因此首选最少 cv 限定的引用,即非 const
限定的函数。
相反,当您拥有:
(const Test{}).begin();
我们正在调用 begin()
并引用 const Test
。所以非 const
限定的函数不是一个可行的候选者(你不能将 const-ref 传递给期望非 const-ref 的函数),所以最好的可行候选者是唯一可行的候选者:int begin() const
。
要记住的几条规则:
不能仅基于 return 类型重载方法。这会导致您的案例 1 中出现错误。
当按值 returning 时,const 限定符是多余的。在你的情况 2 中,编译器警告你这一点。
class 的每个非静态方法都有一个隐式参数。在方法调用时,this 被分配给调用该方法的实例。方法声明末尾(方法体之前)的 const 关键字适用于此隐式参数。您实质上是在说函数体不会修改实例的状态(数据成员)。如果在 const 实例上调用该方法,则需要定义 const 方法。此外,您可以仅根据是否为 const 的事实来重载该方法。