Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is it a good practice to make a method which modifies data outside the class const?

I would like to ask a question about methods' const-correctness. Let me illustrate the situation.

class MyClass
{
public:
    ...
    void DiscussedMethod() { otherClass->NonConstMethod(); }

private:
    OtherClass *otherClass;
};

I have a class MyClass which keeps a pointer to OtherClass. In DiscussedMethod it calls OtherClass::NonConstMethod which modifies some visible data.

I would like to know, whether it would be a good practice to make the DiscussedMethod const (since it doesn't modify any member data)? Would it be a bad practice? Or is both fine?

What if the OtherClass kept a pointer to the MyClass and in NonConstMethod modified some of the MyClass' data (meaning that the MyClass member data would change during the DiscussedMethod call). Would it be a bad practice to make the DiscussedMethod const then?

As far as I've been able to find out, the const on a method is mostly a code documenting thing, so I would probably lean toward to not making the DiscussedMethod const, but I would like to hear your opinions.

EDIT: Some replies take the into account whether the object pointed to by otherClass is owned by the MyClass object. This is not the case in the scenario I'm working with. Lets say that both objects exist independently side by side (with the ability to modify each other). I think this analogy describes my situation quite well.

For example consider something like doubly-linked list, where each element is a class that keeps pointer to its neighbours and member variable color. And it has method MakeNeighboursRed which changes the color of its neighbours but doesn't affect the calling object's state itself. Should I consider making this method const?

And what if there was some possibility that MakeNeighboursRed would call neighbour's MakeNeighboursRed. So in the end the state of the object for which MakeNeighboursRed has been called originally would change as well.

And I would like to thank you all for your opinions :-)

like image 952
Bret Brodak Avatar asked Sep 22 '14 10:09

Bret Brodak


People also ask

Why it is good practice to declare as many methods as const as you can?

A function becomes const when the const keyword is used in the function's declaration. The idea of const functions is not to allow them to modify the object on which they are called. It is recommended practice to make as many functions const as possible so that accidental changes to objects are avoided.

Which data member of a class can be modified by const functions?

The const member functions are the functions which are declared as constant in the program. The object called by these functions cannot be modified. It is recommended to use const keyword so that accidental changes to object are avoided. A const member function can be called by any type of object.

Can we alter/modify the values of data members of a class inside const member function?

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

Can const methods be used by non-const objects?

const member functions may be invoked for const and non-const objects. non-const member functions can only be invoked for non-const objects. If a non-const member function is invoked on a const object, it is a compiler error.


1 Answers

If MyClass owns the OtherClass instance i wouldn't make DiscussedMethod constant.

The same goes for classes, managing resources. I.e. the standard containers do not return non const references or pointers to the managed memory using const functions, although it would be "possible" (since the actual pointer holding the resource is not modified).

Consider

class MyClass
{
public:
    bool a() const { return otherClass->SomeMethod(); }
    void b() const { otherClass->NonConstMethod(); }
private:
    OtherClass *otherClass;
};

void foo (MyClass const &x)
{
    cout << boolalpha << x.a() << endl;
    x.b(); // possible if b is a const function
    cout << boolalpha << x.a() << endl;
}

The foo could print two different values although an implementor of foo would probably expect that two function calls on a const object will have the same behaviour.

For clarification:

The following is invalid according to the standard since the const version of operator[] returns std::vector<T>::const_reference which is a constant reference to the value type.

std::vector<int> const a = { /* ... */ };
a[0] = 23; // impossible, the content is part of the state of a

It would be possible if there was only one signature of this function, namely referece operator[] (size_t i) const;, since the operation does not alter the internal pointers of the vector but the memory they point to.

But the memory, managed by the vector is considered to be part of the vectors state and thus modification is impossible through the const vector interface.

If the vector contains pointers, those pointer will still be unmodifiable through the public const vector interface, although the pointers stored in the vector may well be non const and it may well be possible to alter the memory they point to.

std::vector<int*> const b = { /* ... */ };
int x(2);
b[0] = &x; // impossible, b is const
*b[0] = x; // possible since value_type is int* not int const *
like image 115
Pixelchemist Avatar answered Oct 22 '22 23:10

Pixelchemist