Question
In C++, what does the const keyword mean when it appears at the end of a member function declaration, as in this class?
class Foo {
public:
int Bar(int randomArg) const {
// code
}
};
How does this affect what the function can do and how it can be called?
Short Answer
A const after a C++ member function declares a const member function. It promises not to modify the observable state of the object it is called on. By the end, you will know what this promise means, why it matters, and how to write and use const-correct classes.
Concept
A member function has an implicit object: the instance before the dot.
Foo item;
item.Bar(42);
Inside Bar, C++ effectively provides access to that object through a hidden this pointer. When the function ends with const:
int Bar(int randomArg) const;
the hidden pointer behaves conceptually like this:
const Foo* const this;
Therefore, the function cannot change ordinary data members or call non-const member functions on the current object.
This is important because many functions only inspect an object: getters, formatters, comparison functions, and calculations. Marking them const documents that behavior and lets them work with const objects and references.
class Counter {
public:
int value() {
count;
}
{
++count;
}
:
count = ;
};
Mental Model
Think of an object as a library book.
- A non-const member function may write notes in the book, erase text, or add pages.
- A const member function is allowed only to read the book.
The const after the function name is a promise from the class author: “Calling this function will not change this object's normal state.”
This differs from const on a parameter. In this declaration:
int Bar(int randomArg) const;
int randomArgis a regular parameter.- The final
constapplies to the object on whichBaris called.
Syntax and Examples
The syntax places const after the parameter list and before the function body or semicolon.
class Temperature {
public:
double celsius() const {
return celsiusValue;
}
void setCelsius(double value) {
celsiusValue = value;
}
private:
double celsiusValue = 0.0;
};
A const member function can:
- Read data members.
- Use its parameters and local variables normally.
- Call other const member functions.
class Temperature {
public:
double fahrenheit() const {
return celsius() * 9.0 / 5.0 + 32.0;
}
double celsius() const {
celsiusValue;
}
:
celsiusValue = ;
};
Step by Step Execution
Consider this class and code:
class Rectangle {
public:
int area() const {
return width * height;
}
void resize(int newWidth, int newHeight) {
width = newWidth;
height = newHeight;
}
private:
int width = 4;
int height = 3;
};
int main() {
const Rectangle card;
int result = card.area();
}
Step by step:
cardis created withwidthequal to4andheightequal to3.cardis declaredconst, so code must not modify it.card.area()is allowed because is declared with a trailing .
Real World Use Cases
Const member functions are common whenever an object is queried without being changed.
- Getters:
user.id() const,product.price() const - Display and logging:
order.toString() const,config.print() const - Calculations:
shape.area() const,cart.total() const - Checks:
file.isOpen() const,queue.empty() const - Comparisons:
account.equals(other) const - Container access: standard-library containers provide functions such as
size() const,empty() const, andbegin() constfor read-only use.
For example, a web service may receive an application configuration as a const Config&. Handler code can read values such as a database host and timeout, but cannot accidentally alter global configuration.
Real Codebase Usage
In production C++ code, const member functions are part of const correctness: expressing which code reads data and which code changes data.
A common pattern is to pass objects by const reference when a function only needs to inspect them:
class User {
public:
const std::string& name() const {
return name_;
}
private:
std::string name_;
};
void printUser(const User& user) {
std::cout << user.name() << '\n';
}
Because printUser receives const User&, it can call only const member functions. This makes accidental changes impossible at compile time.
Classes often provide two overloads for accessors that return references:
class Document {
public:
std::string& title() {
return title_;
}
const std::string& title() const {
title_;
}
:
std::string title_;
};
Common Mistakes
Trying to modify a member in a const function
class Score {
public:
void reset() const {
points = 0; // Error
}
private:
int points = 10;
};
Remove const if resetting is part of the function's purpose.
Forgetting const on a getter
class Book {
public:
int pages() { // Missing const
return pages_;
}
private:
int pages_ = 250;
};
void printPages(const Book& book) {
// book.pages(); // Error: pages() is not const
}
Add trailing const when the function only observes the object.
Confusing trailing const with a const return value
Comparisons
| Declaration | What is const? | Can it modify the current object? |
|---|---|---|
int size() const; | The member function's object (*this) | No, except mutable members |
int print(const int value); | The local parameter value | Unrelated to the current object |
const std::string& name() const; | The returned referenced string and the current object | No |
void update(); | Nothing is const | Yes |
A const and non-const member function may have the same name and parameters because their const qualification differs:
class {
:
{
data_[index];
}
{
data_[index];
}
:
std::string data_ = ;
};
Cheat Sheet
class Example {
public:
int read() const; // Does not modify ordinary members
void write(int x); // May modify members
};
- Put
constafter()in a member function declaration. - A const member function may read members.
- It cannot assign to normal members or call non-const member functions on
*this. - A const object can call only const member functions.
- Prefer
constfor getters, checks, formatting, and calculations that do not change the object. mutablemembers may change in const functions; use this sparingly.conston a parameter and trailingconston a member function have different meanings.- In an overload pair, const objects select the
constoverload.
FAQ
Can a const member function change local variables?
Yes. Local variables belong to the function call, not to the object.
int doubled() const {
int result = value_ * 2;
return result;
}
Can a const member function call another member function?
Yes, but normally only another const member function. A non-const function might modify the object.
Does trailing const make the entire object permanently const?
No. It applies only while executing that particular member function. Non-const functions can still modify a non-const object.
Why does a getter need const?
Without it, the getter cannot be called through a const object or const reference, which is common in function parameters and APIs.
Can constructors be const?
No. Constructors initialize a new object and cannot have a trailing const qualifier.
What is a mutable member in C++?
A mutable data member may be changed even in a const member function. It is commonly used for implementation details such as cached results, not for normal object state.
Is const after a function the same as before a return type?
Mini Project
Description
Build a small BankAccount class that separates read-only account operations from operations that change the balance. This reflects real code where reporting code should inspect account data without being able to modify it.
Goal
Create a class whose read-only methods work with a const BankAccount reference while deposit and withdrawal methods remain state-changing operations.
Requirements
Implement a BankAccount class with an owner name and balance.
Add a const owner() method that returns the account owner.
Add a const balance() method that returns the current balance.
Add a deposit() method that increases the balance.
Add a const canAfford() method that checks whether a requested amount is available.
Write a function that prints account details through a const BankAccount&.
Keep learning
Related questions
Advantages of Brace Initialization in C++
Learn why C++ brace initialization is often clearer and safer than other object initialization styles, with examples and common pitfalls.
Basic Rules and Idioms for Operator Overloading in C++
Learn the core rules, syntax, and common idioms for operator overloading in C++, including member vs non-member operators.
C++ Aggregates, Trivial Types, Trivially Copyable Types, and PODs Explained
Learn what aggregates, trivial types, trivially copyable types, and PODs mean in C++, how they differ, and why they matter.