4

In the following example I found on the net, it is mentioned that one of the advantages of const_cast is that it allow a constant function changes the class members. It is a question to me. Why should we set a rule for a function by const and then breaking that rule with const_cast? Isn't it like a cheating? Wouldnt it better to not set const for the function at all?

#include <iostream>
using namespace std;

class student
{
private:
    int roll;
public:

    student(int r):roll(r) {}

    // A const function that changes roll with the help of const_cast
    void fun() const
    {
        ( const_cast <student*> (this) )->roll = 5;
    }

    int getRoll()  { return roll; }
};

int main(void)
{
    student s(3);
    cout << "Old roll number: " << s.getRoll() << endl;

    s.fun();

    cout << "New roll number: " << s.getRoll() << endl;

    return 0;
}

reference

barej
  • 1,330
  • 3
  • 25
  • 56
  • 5
    funny that getter is not `const`. – Jarod42 Feb 09 '15 at 14:07
  • C++ provides many ways to shoot yourself in the foot, this is one of them. – Anton Savin Feb 09 '15 at 14:09
  • 1
    I thought one of the main justifications for const_cast was to be able to call older C API functions that did not correctly declare their parameters as const (frequently, pointer to const). This would make these API uncallable from const methods (operating on const members). But you may know that the function doesn't change its parameters (say, strcmp). const_cast would let you strip off the const in order to be able to use that function. – Andre Kostur Feb 09 '15 at 15:32

4 Answers4

5

That is indeed a bad idea. As well as lying about the function's behaviour, it allows you to modify a member of a constant student object, giving undefined behaviour.

In general, a member function should be const if, and only if, it doesn't modify the object's observable state. So in this case, it should not be const.

Sometimes, you might want specific members to be modifiable in a function that doesn't otherwise cause an observable change; for example, locking a mutex to access shared data, or caching the result of a complex calculation. In that case, declare those members mutable, so that the rest of the class is still protected by const-correctness.

Mike Seymour
  • 249,747
  • 28
  • 448
  • 644
2

This is a poor example of const_cast usage. Imagine a better example. A method of a published class was not declared as const by mistake. You have a const-reference to this class and want to call this method. But you cannot do it, because it was not declared as const by mistake. In this case, you can say to the compiler: "Ok, I know what I'm doing, I know this method does not actually change anything, just remove const-ness from that reference and allow me to call this method. Trust me, I'm a programmer".

Real-life example. In OpenCV library, there is no such thing as immutable image. The core class cv::Mat is mutable. Suppose you want to create a read-only wrapper around a constant buffer of memory. The only way you can construct it is by casting const away, like this:

const char* myConstBuffer = GetConstBuffer();
const cv::Mat myConstImage(const_cast<char*>(myConstBuffer), /* dimensions, etc. */);

This is a legal code, since constructed image has type const cv::Mat and you cannot call any modifying methods on it. But using const_cast here still reveals a design error: there should be a valid way to construct such read-only buffers.

Mikhail
  • 20,685
  • 7
  • 70
  • 146
0

const is mostly about expressing intention to callers. When a member function is marked const, you're telling callers that they can expect the public interface of this object not to change.

But imagine a scenario where you want to log calls to this function, with a serial number. That serial number will need to change, but this change is only visible inside the private depths of the class. It's appropriate in this case to "cheat" const my marking the serial number variable as mutable.

const_cast is similar rationale.

tenfour
  • 36,141
  • 15
  • 83
  • 142
  • 2
    I don't think `const_cast` is appropriate in this case. Sounds like the perfect case for `mutable`. – Mikhail Feb 09 '15 at 14:11
0

The bright example - reference-counting object. In fact reference counting declares object life-time policy, but doesn't relates to real "business" flow of class implementation. While const relates to business flow. For example - you have business account, but have no ability to change it:

class BusinessAccount{
   unsigned _refcount;
   double _amount
   ...

You have some operation to "view"

void view(SmartPtr<BusinessAccount> smart_ptr)

So if view have to take ownership on object - it must increase _refcount.

PS the better solution there keyword - mutable on field _refcount instead of const_cast

Dewfy
  • 23,277
  • 13
  • 73
  • 121