Imagine the following example:
class A
{
public:
void doSomeStuff() { std::cout << "SomeStuff" << std::endl; }
};
class B
{
public:
B(A& a) : a(a) {}
void constStuff() const { a.doSomeStuff(); }
private:
A &a;
};
If doSomeStuff()
would change the data, wouldn't that affect class B
as well? Why is such behaviour allowed?
Once you have a const object, it cannot be assigned to a non-const reference or use functions that are known to be capable of changing the state of the object. This is necessary to enforce the const-ness of the object, but it means you need a way to state that a function should not make changes to an object.
If the function is non-constant, then the function is allowed to change values of the object on which it is being called. So the compiler doesn't allow to create this chance and prevent you to call a non-constant function on a constant object, as constant object means you cannot change anything of it anymore.
Any attempt to change a data member of the object that called a constant method will result in a syntax error, as will attempting to call a non- const member function for that object. Constant objects can only call constant member functions. Non-constant objects can call both constant and non-constant member functions.
Do not return non-const handles to Class data from const member Functions. From a language point of view, the pointer 'p' is part of the class and then cannot be modified in a 'const' function. But the pointed-to value is not part of the class, and may be modified.
If doSomeStuff() would change the data, wouldn't that affect class B as well?
Well, not in the way a compiler checks for const correctness. A B
holds a reference to an A
. That object can reside anywhere, but most importantly it doesn't reside inside the B
object. So modifying it does not do something with undefined behavior like changing a const object. We have a reference to a non-const object, so it's possible to modify the object via the reference. That's as far as the C++ type system cares, whether or not the object is maybe physically const.
It will probably affect the logical state of the B
, but it is the responsibility of the programmer to ensure the class invariants hold. C++ will not hold your hand in that endeavor.
The original object of the class A will be changed.
When you are using a const member function then the function deals with const T *this
where T is the class type.
That is data members of the object are considered constant.
For a referenced type it could look like
A & const a;
However references themselves can not be constant.
That is for example this declaration
int x;
int & const rx = x;
is invalid and does not mean the same as
const int & rx = x;
So the class B has a reference that points to a non-constant object and using the reference the object can be changed.
Compare with the following declaration of the class B
class B
{
public:
B(A * a) : a(a) {}
void constStuff() const { a.doSomeStuff(); }
private:
A *a;
};
Then then a constant member function is used the data member is considered like
A * const a;
(pointers themselves may be constant) that is the pointer itself that is constant not the object pointed to by the pointer and you can not change the pointer itself but you can change the object pointed to by the pointer.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With