简体   繁体   中英

Good practice: Constant to non-constant cast

When a function doesn't modify an object argument, I always make it ask for a constant reference even if the referenced object isn't really constant. Is this wrong?

For a wrapper class, I'd like to write this:

template<class B>
class Wrapper{
private:
  B* base_;
public:
  Wrapper(const B& b) { base_ = const_cast<B*>(&b); }
  void ModifyBase();
};

The constructor doesn't modify the base so it asks for a constant reference.

The wrapper have some methods who will need to modify the base so it needs to store a non-constant pointer (thus the conversion).

I feel my solution is not the best.

Is there a better way to do this?

Is there any accepted convention?

When you choose your parameter to be a const reference, you're telling the user "You can trust that if you pass me an object, it will not get modified [through this reference]†." You should do that as often as possible, because the user can understand more about what your function will and won't do just from looking at the types. Also, passing around mutable references can lead to code that is difficult to reason about.

However, in your question, your const is not telling the truth. It is casting away the const ness and storing a non- const pointer - this means the object may very well get modified. You lied to the user! It doesn't matter that the constructor itself does nothing to do the object. It allows it to be modified by other member functions. This is bad behaviour. Your constructor should not take a const reference.

Not only that, but your current implementation allows undefined behaviour. Even if an object that is originally declared as const is given to your Wrapper , it doesn't care. It casts away it's const ness and allows the other member functions to modify it. Modifying an object that was originally const is undefined behaviour.

† See 6502's comment

It doesn't really matter that the ctor won't alter the object in the ctor , what happens after the ctor is done is why you need a non- const object pointer to B . So it has to do with ownership and lifetime of the B object passed in: if you want to take ownership (via the & reference, then the object must be non- const because it can be altered. If you want to simply copy the B object passed in, then don't use a refernce, pass by value and store a pointer to the copy.

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