Overload resolution C++ for const member functions

2019-02-15 00:11发布

问题:

Assume you have a class T with two member functions

  1. char foo() const {...}
  2. char foo() {...}.

It is my understanding that when called for a constant T, we resolve to (1); and for a non-constant T, we resolve to (2). 

  1. is that correct?   
  2. which rule is invoked in this resolution? (reference to standard great, but a helpful brief summary appreciated) 

Notes:

  1. I tried to google for it, but old hits I got on SO were cases for other overload resolutions involving const. However, link to an old SO actually explaining the above obviously great.     

  2. This came up when re-reading Stroustrup's "The C++ programming language", 2nd edition ("Special Edition"), String/Cref example in section 11.12, p. 296. As Stroustrup is so precise, the answer might be in previous sections, but I fail to see where. Reference to sections in Stroustrup very welcome too (2nd edition best as this is the one I have). Section 10.2.6 introduces const members as those "that don't change an object's value", which hints at the answer, but doesn't strike me as a clear resolution directive.

回答1:

In N3242 (the standard draft I have on hand), 13.3.1 paragraph 4 says

the type of the implicit object parameter is "lvalue reference to cv X” for [non-static member] functions declared without a ref-qualifier or with the & ref-qualifier

this means that type of the implicit object argument, which occurs first, is an "lvalue reference to cv X", where X is the class, and cv is the cv-qualification of the member variable (i.e. const or non-const). Then, overload resolution continues as normal.

To review the overload resolution process, first, both are listed as "candidate" functions as they are in the correct scope and have the correct name.

In the const case, only the const member function gets to the next step (called "viability"), so it's automatically the best choice. The non-const member function is not viable because you can't convert a const reference into a non-const reference.

In the non-const case, both the const and non-const versions are viable, but the non-const one is "better" because of the fifth rule of 13.3.3.2 paragraph 3, quoted below.

Standard conversion sequence S1 is a better conversion sequence than standard conversion sequence S2 if ...

S1 and S2 are reference bindings, and the types to which the references refer are the same type except for top-level cv-qualifiers, and the type to which the reference initialized by S2 refers is more cv-qualified than the type to which the reference initialized by S1 refers.