two versions of class-member function: with and without const

Hello,

I have noticed that there are classes in the C++ Standard library which have member functions that have two versions - one with and another without const qualifier. The name is the same, the parameter list is the same and the only difference is that one version has const the other does not and the return values differ. Since the parameter lists in these member functions are the same I do not consider two versions as overloading.


EXAMPLES:

1) STL container classes have few member functions which have two versions, one with and another without const. Some of them are: begin, end, front, back...

For example STL container class list has member function front which has these two versions:

reference front ( );
const_reference front ( ) const;

http://www.cplusplus.com/reference/stl/list/front/


Another example is STL container class vector which has member function at which has these two versions:

const_reference at ( size_type n ) const;
reference at ( size_type n );

http://www.cplusplus.com/reference/stl/vector/at/

Again, the name of the member function is the same, parameter list is the same, and the only difference is the const qualifier and the type of the return value.



2) Numeric class valarray has member function operator[] which is overloaded (it has several versions with different parameter lists) but for each parameter list version it has two sub-versions: one with and another without const:

T operator[] (size_t n) const;
T& operator[] (size_t n);

valarray<T> operator[] (slice slc) const;
slice_array<T> operator[] (slice slc);

valarray<T> operator[] (const gslice& gslc) const;
gslice_array<T> operator[] (const gslice& gslc);

valarray<T> operator[] (const valarray<bool>& msk) const;
mask_array<T> operator[] (const valarray<bool>& msk);

valarray<T> operator[] (const valarray<size_t>& ind) const;
indirect_array<T> operator[] (const valarray<size_t>& ind);

http://www.cplusplus.com/reference/std/valarray/valarray/operator%5B%5D/

Again, notice that each overloaded version has two sub-versions which differ in the presence of const and the type of the return value.


END OF EXAMPLES


Now, I do understand that const qualifier appended to a member function declaration tells the compiler that the function will not modify the invoking object. I also understand that objects qualified with const in their declarations can invoke only those member functions which have const in their declarations. Objects which are not qualified with const in their declarations can invoke both const-qualified and const-not-qualified member functions.

However I do not understand how it is possible to have two versions of the same function which have the same name, the same parameter list (therefore it is not overloading) but that have two different return value types and one having the other not having const!?!

QUESTIONS:

1) How does the compiler know which version of the function to invoke if the parameter list is the same?
2) Does the const qualification of the invoking object determine which member function version to invoke?


thank you in advance for your answers and cooperation.

best regards
The compiler always choose the non-const version if possible. On const objects the const version will be used.
> Since the parameter lists in these member functions are the same I do not consider two versions as overloading.

In addition to the parameters specified in the declaration, a non-static member function of a class has a this pointer (which is like an implied extra parameter of the function for purposes of this discussion). cv-qualifiers applied to a non-static member function affect the type of the this pointer. In effect, this means that we can overload a a non-static member function on the type of the this pointer - and normal overload resolution rules would apply.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
struct A
{
    void bar( /* A* this */ ) { std::cout << "A::bar()\n" ; } 
    
    void bar( /* const A* this */ ) const { std::cout << "A::bar() const\n" ; }
    
    void bar( /* volatile A* this */ ) volatile 
    { std::cout << "A::bar() volatile\n" ; }
    
    void bar( /* const volatile A* this */ ) const volatile 
    { std::cout << "A::bar() const volatile\n" ; }
};

int main()
{
    A a ;
    { A* This = &a ; This->bar() ; } // A::bar()
    { const A* This = &a ; This->bar() ; } // A::bar() const
    { volatile A* This = &a ; This->bar() ; } // A::bar() volatile
    { const volatile A* This = &a ; This->bar() ; } // A::bar() const volatile
}


The volatile qualifier is esoteric and is rarely used in practice.

The const qualifier on the other hand is very common and is fundamental to writing "const-correct" code.
http://www.parashift.com/c++-faq-lite/const-correctness.html
Topic archived. No new replies allowed.