Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Calling non-const function of another class by reference from const function [duplicate]

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?

like image 352
Quest Avatar asked Aug 08 '19 11:08

Quest


People also ask

Can a const reference call a non-const function?

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.

What will happen if a const object calls a non-const member function?

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.

Can a constant member function call a non-constant member function?

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.

Can a const function return a non-const pointer?

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.


2 Answers

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.

like image 135
StoryTeller - Unslander Monica Avatar answered Sep 23 '22 15:09

StoryTeller - Unslander Monica


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.

like image 22
Vlad from Moscow Avatar answered Sep 22 '22 15:09

Vlad from Moscow