8.6. const member functionsΒΆ

We have previously mentioned uses for const, and classes add another situation where the const keyword can be used.

An object can be created with the const cv qualifier, just like any other type:

const int x = 3;

const fibonacci foo = {5, 8, 13};

When created const, then no changes are allowed to the object. It is OK to call a non-modifying member function.

How does the compiler know that a function is a non-modifying member function? When the function is declared as const.

Create a const member function by inserting the const keyword after the parameter list and before the function body:

bool verbose() const {
  return true;
}

Here const tells the compiler this function will not change the object state.

It is a promise. If a const function attempts to change any class member, then a compile error results.

Note

Only class member functions can be marked const.

Attempting to mark a free function as const is a compile error.

Because const changes which objects can call a member function, it is part of the member function signature. This means a class can provide both a const and non-const version of the same function.

Why is this important?

A const object can only call const member functions. Any attempt to call a non-const member function is a compile error.

Const and non-const member function overloads
 1#include <iostream>
 2#include <string>
 3#include <utility>
 4
 5class dog {
 6  std::string name_;
 7
 8public:
 9  explicit dog(std::string name)
10    : name_{std::move(name)}
11  {
12  }
13
14  std::string& name() {
15    return name_;
16  }
17
18  const std::string& name() const {
19    return name_;
20  }
21};
22
23int main() {
24  dog rover{"Rover"};
25  const dog fido{"Fido"};
26
27  rover.name() = "Spot";
28
29  std::cout << "non-const dog: " << rover.name() << '\n';
30  std::cout << "const dog: " << fido.name() << '\n';
31}

The two name functions have the same name and the same parameter list. The trailing const makes them different member function signatures. When the object is not const, overload resolution chooses the non-const version, which returns a modifiable reference. When the object is const, overload resolution chooses the const version, which returns a reference that cannot be used to modify the object.

Given the following:

#include <iostream>

class counter {
  int value_ = 0;

public:
  counter() = default;

  void set_value(int value) {
    value_ = value;
  }

  int value() const {
    return value_;
  }
};

int main() {
  const counter count;
  count.set_value(13);
  std::cout << count.value() << '\n';
}

What is the output? Choose the one correct answer.


More to Explore