Let us take this code as an example
#include <iostream>
using namespace std;
struct valStruct {
double& operator[](int i){return values[i];}; //line 6
double operator[](int i) const {return values[i];}; //line 7
double values[4];
};
int main () {
valStruct vals = {0,1,2,3};
cout << "Value before change" << endl;
for ( int i = 0; i < 3; i++ ) {
cout << "vals[" << i << "] = "<< vals[i] << endl;
}
vals[1] = 2.2; // change 2nd element
cout << "Value after change" << endl;
for ( int i = 0; i < 3; i++ ) {
cout << "vals[" << i << "] = "<< vals.values[i] << endl;
}
return 0;
}
I understand that line 6 (see comment in code) enables the writing (and reading!?) of a value to the index in array values while line 7 only reads that value.
I understand the need of the const declaration in line 7 as preventing changing the value while not intended (although I do not understand how since line 6 exists), but my question is, why cannot I write the line as
double& operator[](int i) const {return values[i];}; //line 7
which throws out the error: binding reference of type ‘double&’ to ‘const double’ discards qualifiers.
This also raises the question of why do we need line 7 at all since line 6 exists and can do both writing and reading.
EDIT:
I understand the idea of a const func() const suggested here and I do not understand how this answers my question. I did not understand the mechanism explained by the two answers given.
>Solution :
why do we need line 7 at all since line 6 exists and can do both writing and reading.
We need line 7 to work on const objects. Line 6 can’t be used on const objects of type valStruct. This is because const class objects can only explicitly call const member functions, and the overloaded operator[] in line 6 has not been marked as a const member function. So it can’t be used on const object of type valStruct. Thus, we need line 7 which "marks" the overloaded operator[] as a const member function.
Now, if you change the return type in line 7 to double&, then the problem is that here you’ve overloaded operator[] as a const member function. This means that the data members are also const. And since we cannot bind an "lvalue reference to non-const object", to a const object, we get the mentioned error. For example,
const double d = 43.4;
double& ref = d;//here we'll get the same error
The situation(of why you’re getting the error) is similar to the above given snippet.