Logical constness is the principle that a const member function doesn't change the object's observable state, even if it modifies internal state (like a cache). The mutable keyword marks members that can be modified by const functions, indicating they don't affect observable behavior.
Use mutable carefully for caches and lazy-initialized state; document why members are mutable so readers understand the invariant.
This example shows logical constness with mutable caching.
// compile: g++ -o logical logical.cpp // run: ./logical // description: logical constness: mutable for internal caches #include <iostream> #include <string> class User { private: std::string first_name; std::string last_name; mutable std::string cached_full_name; mutable bool cache_valid = false; public: User(const std::string& f, const std::string& l) : first_name(f), last_name(l) {} const std::string& fullName() const { if (!cache_valid) { cached_full_name = first_name + " " + last_name; cache_valid = true; } return cached_full_name; } }; int main() { const User u("John", "Doe"); std::cout << u.fullName() << "\n"; // const function, but modifies mutable cache return 0; }