成员函数的const修饰符如何影响重载解析?(How does const modifier for member functions affect overload resolution?)

编程入门 行业动态 更新时间:2024-10-26 22:23:24
成员函数的const修饰符如何影响重载解析?(How does const modifier for member functions affect overload resolution?)

我有以下测试代码:

#include <string> #include <iostream> class CString { public: CString(char const*) {} }; class TestBed { public: void Comparison(CString const&) { std::cout << "CString Overload" << std::endl; } void Comparison(std::string const&) { std::cout << "std::string overload" << std::endl; } }; int main() { TestBed tb; tb.Comparison("Hello World"); }

此代码无法编译,因为对Comparison()的调用不明确。 我期待这种行为。

然而,当我使任何Comparison()重载const ,如下所示:代码编译和选择非void Comparison(CString const&) const ( void Comparison(CString const&) const void Comparison(std::string const&) const或void Comparison(CString const&) const const超载。

重载解析规则非常复杂,我没有看到任何描述const如何影响这种情况的东西。 我的理解是:

首先选择具有精确匹配参数的函数 下一步尝试1级隐式转换

在这两种情况下,1和2都是不明确的。 有人可以解释这个吗? 谢谢。

I have the following test code:

#include <string> #include <iostream> class CString { public: CString(char const*) {} }; class TestBed { public: void Comparison(CString const&) { std::cout << "CString Overload" << std::endl; } void Comparison(std::string const&) { std::cout << "std::string overload" << std::endl; } }; int main() { TestBed tb; tb.Comparison("Hello World"); }

This code fails to compile because the call to Comparison() is ambiguous. I expect this behavior.

However, when I make either of the Comparison() overloads const, as in: void Comparison(std::string const&) const or void Comparison(CString const&) const (but not both), the code compiles and chooses the non-const overload.

Overload resolution rules are pretty complex and I haven't seen anything that describes how const affects this situation. My understanding is:

Function with exact matching argument is chosen first 1-level implicit conversion is tried next

In both cases, 1 & 2 are ambiguous. Can someone explain this? Thanks.

最满意答案

对于类方法, this部分被认为是一个额外的参数。 所以,如果你使CString成为一个常量,那么会导致重载:

Comparison(const TestBed&, CString const&) // (1) Comparison(TestBed&, std::string const&) // (2)

对于(1) ,我们需要进行两次转换: const转换和转换为CString 。 但对于(2) ,我们只需要进行一次转换即可: std::string 。 因此, (2)是优选的。

我们可以通过添加第三个函数来进行验证,该函数为此执行一次单独的转换:

Comparison(const TestBed&, const char*) // (3)

在这里,我们再次只有一次转换(在“第一个”参数中),因此过载集合是不明确的。


在[over.match.funcs]中:

一个成员函数被认为具有一个额外的参数,称为隐式对象参数,它表示已经调用成员函数的对象。 为了重载解析的目的,静态和非静态成员函数都有一个隐含的对象参数,但构造函数不会。

对于非静态成员函数,隐式对象参数的类型为

- 对于不带ref-qualifier或带有&ref-qualifier声明的函数,“左值引用cv X”

- 对于用&& ref-qualifier声明的函数,“cv X的右值引用”

其中X是函数所属的类,cv是成员函数声明中的cv限定。 [例如:对于X类的const成员函数,额外参数被假定为具有“对const X的引用”类型。 - 例子]

在重载解析期间,隐含的对象参数与​​其他参数无法区分。

这确立了我们为什么考虑const TestBed& vs TestBed& 。 然后,它只是比较重载(1)和(2)之间的转换序列的问题。 对于第二个参数,两个转换序列是相等的,但对于第一个参数, (2)具有更好的转换序列(即精确) - 这就是为什么它没有歧义地获胜。

For class methods, the this part is considered as if it were an extra argument. So if you made the CString one const, that makes the overload set:

Comparison(const TestBed&, CString const&) // (1) Comparison(TestBed&, std::string const&) // (2)

For (1), we need to do two conversions: a const conversion, and a conversion to CString. But for (2), we only need to do a single conversion: to std::string. Thus, (2) is preferred.

We can verify this by adding a third function that does one single conversion for this:

Comparison(const TestBed&, const char*) // (3)

Here, we again only have a single conversion (in the "first" argument), and thus the overload set is ambiguous.


In [over.match.funcs]:

a member function is considered to have an extra parameter, called the implicit object parameter, which represents the object for which the member function has been called. For the purposes of overload resolution, both static and non-static member functions have an implicit object parameter, but constructors do not.

For non-static member functions, the type of the implicit object parameter is

— “lvalue reference to cv X” for functions declared without a ref-qualifier or with the & ref-qualifier

— “rvalue reference to cv X” for functions declared with the && ref-qualifier

where X is the class of which the function is a member and cv is the cv-qualification on the member function declaration. [ Example: for a const member function of class X, the extra parameter is assumed to have type “reference to const X”. —end example ]

During overload resolution, the implied object argument is indistinguishable from other arguments.

That establishes why we consider const TestBed& vs TestBed&. And then it's just a matter of comparison the conversion sequences between the overloads (1) and (2). For the 2nd argument, both conversion sequences are equal, but for the 1st argument, (2) has a better conversion sequence (namely Exact) - which is why it wins without ambiguity.

更多推荐

本文发布于:2023-08-01 12:14:00,感谢您对本站的认可!
本文链接:https://www.elefans.com/category/jswz/34/1357910.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
本文标签:函数   成员   修饰符   const   modifier

发布评论

评论列表 (有 0 条评论)
草根站长

>www.elefans.com

编程频道|电子爱好者 - 技术资讯及电子产品介绍!