What Can a 'Const' Method Change

What can a 'const' method change?

Most succinctly, it means that the type of this is const T * inside const member functions, where T is your class, while in unqualified functions it is T *.

Your method set does not change data, so it can be qualified as const. In other words, myclass::data is accessed as this->data and is of type int * const.

Is it possible change value of Member variable within const function?

Though this is not appreciated, but C++ provides “Backdoors” which can be used to breach its own regulations, just like dirty pointer tricks. Anyway, you can easily do this by using a casted version of “This” pointer :

class A (){
int x;
public:
void func () const {
//change value of x here
A* ptr = const_cast<A*> (this);
ptr->x= 10; //Voila ! Here you go buddy
}
}

const method modifies object using reference

Remember that having a "const pointer" like const Thing* or a "const reference" like const Thing& does NOT mean that the const-qualified object cannot change while you have the pointer/reference. It only means that you can't use that particular pointer/reference as a way of changing it. But there could be other names, pointers, or references that do allow changing it.

A couple of examples:

void f1(const int& arg1, int& arg2) {
std::cout << "arg1 before: " << arg1 << "\n";
arg2 = 4;
std::cout << "arg1 after: " << arg1 << "\n"; // same thing?
}

f1 might look as though it must always print the same value in the "before" and "after" lines. But not if someone passes the same int object to both arguments:

void call_f1() {
int n = 7;
f1(n, n); // Prints before 7, after 4!
}

Or if a function call comes between two uses of a const reference, that can similarly change a variable in some way:

void something_else();
void f2(const int& arg) {
std::cout << "arg before: " << arg << "\n";
something_else();
std::cout << "arg after: " << arg << "\n";
}

int n = 2;
void something_else() { n = 8; }

void call_f2() {
f2(n); // Prints before 2, after 8!
}

So it's true that in your void A::calc(int& j, const int value) const function, the this pointer is const A* const, which means you can't change the A object using the this pointer. But there can still be other ways to change it, like here you have an int& j reference to non-const object. If it so happens that j refers to a subobject of *this, then modifying j is a valid way of modifying the subobject of *this. This is similar to my f1 example above, where arg1 can't be used to change the referenced int, but arg2 can, and if they refer to the same int, this means arg1 has changed.


The case is slightly different when a variable is defined with the const qualifier in the first place. If we write

const A a(3);

then we do get a guarantee that (except during the constructor and destructor), the object can't be changed in any way. The language will usually prevent you from accidentally trying, like with a.set1(), but even if you try const_cast tricks, any actual change would then be undefined behavior.

Why can I modify the class with a const function in C++11?

It is because you do not modify it. When you do:

int* tab

tab contains only an address. Then in

void DArray::setValue(unsigned n, int value) const // HERE
{
tab[n] = value;
}

You do not modify this address, you modify some memory after it. Thus you do not modify your class.

If instead, you used

std::vector<int> tab

You would have an error in setValue because you would modify an element of your class.

Why can a const member function modify a static data member?

It's the rule, that's all. And for good reason.

The const qualifier on a member function means that you cannot modify non-mutable non-static class member variables.

By way of offering some rationalisation, the this pointer in a const qualified member function is a const type, and this is inherently related to an instance of a class. static members are not related to a class instance. You don't need an instance to modify a static member: you can do it, in your case, by writing A::a = 10;.

So, in your first case, think of a = 10; as shorthand for A::a = 10; and in the second case, think of it as shorthand for this->a = 10;, which is not compilable since the type of this is const A*.

Why is it possible to modify object state via const member function that uses pointer to the object's member?

During the construction and destruction of an object, the members are not const. That means you can store a non-const pointer to a member that is going to be const once the object is constructed. Using that pointer to change value of a const object is undefined behavior. Quoting cppreference:

Modifying a const object through a non-const access path and referring to a volatile object through a non-volatile glvalue results in undefined behavior.

And quoting [dcl.type.cv]/4:

Except that any class member declared mutable can be modified, any attempt to modify a const object during its lifetime results in undefined behavior.

const member function can modify data member

The calculator class has a const member function called calculateStart() which sets (i.e. modifies) the reference returned from calling the Parms() function in the Calculator class.

Yes, calculateStart() does modify the Calculator object, which is unexpected considering the final const qualifier in its definition.

Why ? Look at definition of inline const ParmsPtr& Layout::parms() const; the final const tells the compiler that the function will not modify the Layout object, though it actually does. How ? By mischeviously const_cast'ing the object to a non-const object; that's where the constness is broken and that's why setParms() can be called.

This is a bad practice, though there may be some reasons to do it. In such cases, const_cast serves this purpose.

Why can I call a method that changes a member from a const method?

The const applies to the pointer itself, f, not to what this pointer is pointing to. The type of f inside your const-qualified member function, Test::test(), is Foo* const (i.e., const pointer to Foo), not const Foo* (i.e., pointer to const Foo). That's why you can modify what the pointer is pointing to in spite of the const qualification of the member function.


Note that the following sample member function, Test::test2(), does fail to compile since it is const-qualified and tries to modify the pointer data member, f:

void Test::test2() const {
f = nullptr; // <-- error
}

C++ const member functions are modifying member variables

Your member variable is not X, but pointer to X. As long as foo does not modify the pointer, it can be const.

Why can reference members be modified by const member functions?

The const qualifier of a class member function indicates that this member function (e.g., foo::operator() const) cannot change the state of the object from the client's point of view (i.e., it's abstract state). This is not exactly the same as saying that the object's raw bits are not going to change.

It is forbitten to C++ compilers to consider objects as raw bits, unless they can resolve the problem of aliasing. which in your case the compiler cannot. This is due to the fact that a non-constant alias exists (i.e., std::string &str) and consequently the state of the object is modifiable.

That is, calling operator() on object a does not change the state of a (i.e., although ext has changed, the str still remains an alias of ext).

The above also explains why pointing at an object with a pointer to constant (i.e., std::string * const str) does not guarantee that the object won't be modified. It only guarantees that the object won't change through that pointer.



Related Topics



Leave a reply



Submit