5

Out of curiosity,

Is it possible to derive making the parent members mutable? Is there any reasonable way to modify the following code and make it compile? (Keeping foo() a const method and int a not mutable when declared in the parent class A)

class A {
protected:
    int a;
};

class B : public A {
public:
    void foo() const {
        a = 10;
    }
};
Antonio
  • 19,451
  • 13
  • 99
  • 197
  • 1
    That clearly violates the `const` promise on `foo()`... However, if you just remove `const`, then you have no modifiers on `a` in `A` but you have one in `B`, doesn't that solve your problem? – Barry Apr 10 '15 at 15:46
  • No. I don't know why it was down voted except to express someone's disgust with what you want to do. It's bad. Stop. – David Apr 10 '15 at 15:46
  • Even if you are changing the parent part you are still changing part of the object which violates the const contract. – NathanOliver Apr 10 '15 at 15:46
  • @NathanOliver Sure, but if `int a;` had been declared `mutable` you could do that. – Antonio Apr 10 '15 at 15:47
  • 1
    @Dave It was more a question drawn by curiosity, today I dropped in a case that *could* have been solved in this way. But I think if you need something like that, it means that `B` is not something that should derive from `A`, but that instead `B` should own an instance of `A` – Antonio Apr 10 '15 at 15:56

2 Answers2

6

Normally, needing to modify a const value means you have a design error elsewhere that needs to be fixed... but if you really need to, you can do so with a const cast; e.g.

const_cast<int&>(a) = 10;

Given that you say you want to treat the base class itself as mutable, you might consider casting away the constness elsewhere, e.g. by making a member function

A& hack() const { return const_cast<B&>(*this); }

and then you can implement foo as

hack().a = 10;

This solution has the drawback of hiding the const_cast behind a function call, so you would need some way to ensure that someone reading your code knows you're doing something 'evil' (e.g. via a well chosen name for the function). This version has some advantages, however:

  • The code is, in my opinion, a bit more readable
  • It doesn't require you to repeat the type of the object you're doing this to
  • It ensures that you are only doing this to members of A, and not to members of B.
  • 1
    Just to confirm, it will give undefined behaviour if my instance of `B` is `const`, correct? – Antonio Apr 10 '15 at 16:44
  • 1
    @Antonio: I've never researched this enough to know exactly what can go wrong and when, so I only have vague ideas on the matter. You'll have to refer elsewhere if you want to know that information;. –  Apr 10 '15 at 17:14
1

You can't as far as I know. This is similar to the question whether you can derive from a "const" base, which would be more likely to be allowed.

It could be possible in principle but it would create lot of surprises: For example, would it mean that you can pass a B const-reference to a function taking an A non-const reference?

Others say that making the a member mutable in the base would solve the problem, but a solution closer to your question would be to use composition rather than inheritance, as in:

struct B{
  mutable A m_a; 
  void foo() const {m_a.a = 10;} 
};

You can add operator A&() const{return m_a;} if you need (a limited form of) polymorphism. (also could would have surprising behavior).

It is not 100% equivalent to a hypothetical mutable-inheritance but it could be even preferable.

alfC
  • 14,261
  • 4
  • 67
  • 118