简体   繁体   中英

A benevolent case for const_cast?

I've read quite a few discussions that const_cast in C++ is considered wrong and dangerous and should not be used for anything other than backward compatibility with C code. And I generally agree.

However recently I came across the following use case and it made me wonder.

I have some model object, owned by a controller, that is generally non-const. I pass it to a view that should not be able to modify the model object, so it would be logical to declare the object as a const parameter when passed to the view. However the view also makes delegate callbacks to the controller, passing the model object as a parameter (eg the user clicked this object). The callback parameter also must be const. In the callback method, the controller wants to make a change to the model, but the model is const so it can't do it.

The two solutions:

  1. use const_cast in the controller's callback method, since it knows the model object is non-const - but it smells.
  2. don't declare the model as const parameter when passed to the view - but then I can't use such a useful tool as the const declaration, which seems very relevant in this case.

Thoughts?

There are two ways to deal with const .

  1. Things are const if this code won't directly change them .

  2. Things are const if this code won't change them .

In this case, the view won't directly change the object. But you want it to indirectly change the object.

Under (2), this means the object isn't const . The view can change the object, if indirectly. It can cause the object to be changed. Saying it is const implies that the views interaction with the object is purely "reading state", not changing the state -- but clicking on the "delete" button of the object and making it delete is a mutating operation.

Under (1), your reference should be const , because you aren't yourself modifying it. Someone else is, under authority granted by their right to do it.

This is one conflict. And (1) is an acceptable way to use const . But when using (1) you should have an alternative route to the object as non- const .

We can see this under vector.erase . It (now) takes const_iterator s. Even though those iterators themselves are not permitted to modify the vector, the non- const ness of *this provides an alternative access path that permits modification.

In your case, the controller owns the object, so should have a non- const access path to that object. That is the path you should use to do non- const modification of the object.

When the view makes a delegate callback, it might pass an identifier instead of an object -- or, the controller might extract the identifier from the object somehow, and look it back up in its own list of objects.

This is not a good case for const_cast . If the view accepts the model as a const then it can be given a truly const instance of model . It would then be incorrect to try to pass that instance to the controller. If the reference to the model given to the view can be used to modify the model , then it must not be const .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM