Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why does this const member function allow a member variable to be modified?

Tags:

c++

constants

class String
{

    private:
        char* rep;

    public:
        String (const char*);
        void toUpper() const;
};


String :: String (const char* s)
{
    rep = new char [strlen(s)+1];
    strcpy (rep, s);
}


void String :: toUpper () const
{
    for (int i = 0; rep [i]; i++)
    rep[i] = toupper(rep[i]);
}


int main ()
{
    const String lower ("lower");
    lower.toUpper();

    cout << lower << endl;
    return 0;
}
like image 980
Mahesh Avatar asked Nov 16 '08 13:11

Mahesh


2 Answers

A const member function, is a member function that does not mutate its member variables.

const on a member function does not imply const char *. Which would mean that you can't change the data in the address the pointer holds.

Your example does not mutate the member variables themselves.

A const on a member function, will ensure that you treat all of your member variables as const.

That means if you have:

int x;
char c;
char *p;

Then you will have:

const int x;
const char c;
char * const p; //<-- means you cannot change what p points to, but you can change the data p points to

There are 2 types of const pointers. A const member function uses the one I've listed above.


A way to get the error you want:

Try changing:

char * rep;

to:

char rep[1024];

And remove this line:

rep = new char [strlen(s)+1];

It will throw the error you are expecting (can't modify members because of const keyword)

Because there is only 1 type of const array. And that means you cannot modify any of its data.


Now the whole system is actually broken with the following example:

class String
{

    private:
        char rep2[1024];
        char* rep;

 ...


 String :: String (const char* s)
 {
    rep = rep2;
    strcpy (rep, s); 
 }

So the lesson to learn here is that the const keyword on member functions does not ensure that your object will not change at all.

It only ensures that each member variable will be treated as const. And for pointers, there is a big diff between const char * and char * const.

Most of the time a const member function will mean that the member function will not modify the object itself, but this is not always the case, as the above example shows.

like image 193
Brian R. Bondy Avatar answered Oct 03 '22 04:10

Brian R. Bondy


The reason is that you don't change rep. If you would, you would find rep = ...; somewhere in your code. This is the difference between

char*const rep;

and

const char* rep;

In your case, the first one is done if you execute a const member-function: The pointer is const. So, you won't be able to reset the pointer. But you will very well be able to change what the pointer points to.

Now, remember rep[i] = ...; is the same as *(rep + i) = ...;. Thus, what you change is not the pointer, but what the pointer points to. You are allowed, since the pointer is not of the second case type.

Solution

  1. The const meaning you are looking at is physical constness. However, a const member-function means your object is logical const. If a change to some content will change the logical constness of your object, for example if it changes some static variable that your object depends upon, your compiler cannot know that your class now has another logical value. And neither it can know that the logical value changes dependent on what a pointer points to: The compiler doesn't try to check logical constness in a const member function, since it cannot know what those member variables mean. This stuff is termed const-correctness.
  2. Use an object that is not just a reference or a pointer: A const member function will make that object const, and will disallow you to change its content. std::string, as proposed by some, or an array of characters (note that an array will disallow you changing its content, as opposed to just a pointer), would be an appropriate choice.
  3. 2.
like image 44
Johannes Schaub - litb Avatar answered Oct 03 '22 04:10

Johannes Schaub - litb