Why can a const member function modify a static data member?

C++FunctionC++11StaticConstants

C++ Problem Overview


In the following C++ program, modifying a static data member from a const function is working fine:

class A 
{
  public:   
    static int a; // static data member
    
    void set() const
    {
        a = 10;
    }
};

But modifying a non-static data member from a const function does not work:

class A 
{
  public:   
    int a; // non-static data member
    
    void set() const
    {
        a = 10;
    }
};

Why can a const member function modify a static data member?

C++ Solutions


Solution 1 - C++

It's the rule, that's all. And for good reason.

The const qualifier on a member function means that you cannot modify non-mutable non-static class member variables.

By way of offering some rationalisation, the this pointer in a const qualified member function is a const type, and this is inherently related to an instance of a class. static members are not related to a class instance. You don't need an instance to modify a static member: you can do it, in your case, by writing A::a = 10;.

So, in your first case, think of a = 10; as shorthand for A::a = 10; and in the second case, think of it as shorthand for this->a = 10;, which is not compilable since the type of this is const A*.

Solution 2 - C++

According to the C++ Standard (9.2.3.2 Static data members)

> 1 A static data member is not part of the subobjects of a class...

And (9.2.2.1 The this pointer)

> 1 In the body of a non-static (9.2.1) member function, the keyword > this is a prvalue expression whose value is the address of the object > for which the function is called. The type of this in a member > function of a class X is X*. If the member function is declared > const, the type of this is const X*,...

And at last (9.2.2 Non-static member functions)

> 3 ... if name lookup (3.4) resolves the name in the id-expression to a > non-static non-type member of some class C, and if either the > id-expression is potentially evaluated or C is X or a base class of X, > the id-expression is transformed into a class member access expression > (5.2.5) using *(this) (9.2.2.1) as the postfix-expression to the > left of the . operator.

Thus in this class definition

class A 
{
  public:   
    static int a; 

    void set() const
    {
        a = 10;
    }
};

the static data member a is not a subobject of an object of the class type and the pointer this is not used to access the static data member. So any member function, non-static constant or non-constant, or a static member function can change the data member because it is not a constant.

In this class definition

class A 
{
  public:   
    int a; 

    void set() const
    {
        a = 10;
    }
};

the non-static data member a is an subobject of an object of the class type. To access it in a member function there is used either a member access syntax of this syntax is implied. You may not use a constant pointer this to modify the data member. And the pointer this is indeed has type const A * within the function set because the function is declared with the qualifier const. If the function had no the qualifier in this case the data member could be changed.

Solution 3 - C++

The thing is, that if a member function of a class A is const, then the type of this is const X*, and thereby prevents non-static data members from being altered (cf, for example, C++ standard):

> 9.3.2 The this pointer [class.this]

>In the body of a non-static (9.3) member function, the keyword this is a prvalue expression whose > value is the address of the object for which the function is called. > The type of this in a member function of a class X is X*. If the > member function is declared const, the type of this is const X*, ...

If a is a non-static data member, then a=10 is the same as this->a = 10, which is not allowed if the type of this is const A* and a has not been declared as mutable. Thus, since void set() const makes the type of this being const A*, this access is not allowed.

If a is a static data member, in contrast, then a=10 does not involve this at all; and as long as static int a by itself has not been declared as const, statement a=10 is allowed.

Solution 4 - C++

The const qualifier on a member function means that you cannot modify non-mutable, non-static class data members.

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionmscView Question on Stackoverflow
Solution 1 - C++BathshebaView Answer on Stackoverflow
Solution 2 - C++Vlad from MoscowView Answer on Stackoverflow
Solution 3 - C++Stephan LechnerView Answer on Stackoverflow
Solution 4 - C++Li KuiView Answer on Stackoverflow