The const Keyword in Function Declaration of Classes in C++

Shikha Chaudhary Feb 16, 2024
  1. the const Keyword in Function Declaration of Classes in C++
  2. the Behavior of a Member Function in C++
  3. the Behavior of a const Member Function in C++
  4. Conclusion
The const Keyword in Function Declaration of Classes in C++

In C++, the const keyword defines those values that will not change and remain constant during the program execution. This sounds pretty simple for variables and the data they hold.

But, how can a function be declared constant, and what needs to be kept unchanged in a function? We will answer all these questions and much more in this article, so keep reading!

Note that the functions that we are looking at here are the ones that belong to a class, that is, member functions.

the const Keyword in Function Declaration of Classes in C++

Before diving into the actual discussion, let us understand the problem statement correctly.

We already know that a class can have data members and member functions. These member functions are usually declared inside the class as follows -

class Demo  // class
{
 public:
  int x;
  int showDemo();  // member function declaration
}

Here, the member function showDemo() belongs to the class Demo. But what does it mean if we add const at the end of the member function like this -

class Demo  // class
{
 public:
  int x;
  int showDemo() const;  // const member function declaration
}

Let us first see how a member function normally behaves in C++ to understand this.

the Behavior of a Member Function in C++

Look at the code given below. Here, we first define a class called Demo with a data member, chocolates, whose value is set to 2, and a member function, Desert().

Inside the member function, along with a welcome statement, we print the original value of the data member, chocolates, and then increment this value by one. Further, we print the incremented value of chocolates in the next statement.

Finally, we create an object, demo, and call the member function Desert() from the main block. Also, we print the value of chocolates using the object demo and dot operator.

#include <iostream>
using namespace std;

class Demo {
 public:
  int chocolates = 2;

 public:
  void Desert()  // member function
  {
    cout << "Hello Chocolates" << endl;
    cout << "Before change: " << chocolates << endl;
    chocolates++;
    cout << "After change: " << chocolates << endl;
  }
};

int main() {
  Demo demo;
  demo.Desert();
  cout << demo.chocolates << endl;
}

Output:

Hello Chocolates
Before change: 2
After change: 3
3

You can see that here, we changed the value of the data member, chocolates, from inside the member function. To emphasize the change more precisely, we print the value of this variable from the main block as well, but we still get the updated value, which is 3.

This example thus implies that we can somehow use a normal member function to change the object.

Here, we have only one class and one object. However, while working with many classes and objects, there are high chances that changes are accidentally made to an object.

To avoid this, we use the const member function of C++.

the Behavior of a const Member Function in C++

Look at the example given below. This code is the same as the previous one, except that we put the const keyword after the member function this time.

#include <iostream>
using namespace std;

class Demo {
 public:
  int chocolates = 2;

 public:
  void Desert() const  // const member function
  {
    cout << "Hello Chocolates" << endl;
    cout << "Before change: " << chocolates << endl;
    chocolates++;
    cout << "After change: " << chocolates << endl;
  }
};

int main() {
  Demo demo;
  demo.Desert();
  cout << demo.chocolates << endl;
}

Output:

In member function 'void Demo::Desert() const':
error: increment of member 'Demo::chocolates' in read-only object
   13 |             chocolates++;
      |             ^~~~~~~~~~

You can see how the output changes by making the member function a constant. This time, the value of chocolates is not incremented, and we get an error.

This example thus implies that we cannot use a const member function to change the object in any way.

By the above two comparisons of member functions, we conclude that the use of const in such function declarations implies that there won’t be any change in any class member. When we add const to a method, the this pointer points to the const object, and thus, we cannot change any data member.

After all that we have learned, we can say that we use the const member functions to avoid changing an object. But then, you might wonder: what is the use of a const object?

When we declare an object as const, it can invoke only the const member functions. This is because a const object cannot be modified, and this non-alteration is only promised by const member functions.

Look at the example below.

Inside the Desert class, we have two member functions, desert() and desert() const. Then, inside the main block, we define two objects, d, and a constant object, dd.

Note some important points about this example:

  1. We have two member functions with the same name. The only difference is that one of them is a const member function.
  2. We have two objects, one of which is a constant object.
  3. We call the member function desert() from both the objects without specifying which object calls which function.
#include <iostream>
using namespace std;

class Desert {
 private:
  int cakes;

 public:
  void desert() { cout << "The first desert function." << endl; }

  void desert() const  // the const member function
  {
    cout << "The second const desert function." << endl;
  }
};

int main() {
  Desert d;              // object of class
  const Desert& dd = d;  // constant object of class
  d.desert();
  dd.desert();
}

Output:

The first desert function.
The second const desert function.

The output clearly shows that the normal member function, desert(), was automatically called by the normal object, d. While, the const member function, desert() const, is automatically invoked by the const object, dd.

The output will change if we remove the const keyword from the object.

int main() {
  Desert d;        // object of class
  Desert& dd = d;  // remove the constant keyword
  d.desert();
  dd.desert();
}

Output:

The first desert function.
The first desert function.

This time both the objects call the first function. This proves that a const object invokes a const member function.

Note that this does not mean we cannot call a const member function on a non-constant object. However, a non-const function can only be called by non-const objects.

So far, so good, but there is an exceptional case. If we use the mutable quantifier with any data member of the class, we can modify the object even in a const method.

Look at this example.

#include <iostream>
using namespace std;

class Demo {
 public:
  mutable int chocolates = 2;  // mutable quantifier
 public:
  void Desert() const  // const member function
  {
    cout << "Hello Chocolates" << endl;
    cout << "Before change: " << chocolates << endl;
    chocolates++;
    cout << "After change: " << chocolates << endl;
  }
};

int main() {
  Demo demo;
  demo.Desert();
  cout << demo.chocolates << endl;
}

Output:

Hello Chocolates
Before change: 2
After change: 3
3

Now this time, we do not get an error like before because we are using the mutable quantifier with the data member chocolates. This is often helpful if we want to count the number of times a method is called.

This is all about a const member function in C++. The more you play with the examples, making little changes here and there, the more clarity you will gain!

To know more about const in C++, refer to this documentation.

Conclusion

In this article, we discussed the concepts of const member functions of C++. A const member function ensures that an object is not accidentally modified, and we can use it with both const and non-const objects.

However, a const object can only revoke a const member function. Also, using the mutable keyword with the data members can change the usual behavior of the const member function and is usually used for counting purposes.

Related Article - C++ Function