5

How do I define a constant in C++, that points to a mutable object?

If I declare

static const CMyClass* IMPL;

and assign

const CMyClass* CSomeClass::IMPL = new CMyClass;

then I can only call const functions on the object. Its internals are locked. This is not what I want.

If I leave off the const qualifier, I can reassign the pointer IMPL, so it isn’t protected as a constant anymore, which it should be. final seems to be applicable only to functions in C++. Is there an equivalent to a Java’s final variables in C++?

Matthias Ronge
  • 9,403
  • 7
  • 47
  • 63
  • So you want the pointer to be not assignable but the pointed to object to be assignable? – NathanOliver Sep 09 '16 at 12:03
  • Even if you don't leave off `const` you can reassign the pointer `IMPL`. – Kerrek SB Sep 09 '16 at 12:15
  • 2
    Possible duplicate of [What is the difference between const int\*, const int \* const, and int const \*?](http://stackoverflow.com/questions/1143262/what-is-the-difference-between-const-int-const-int-const-and-int-const) – LogicStuff Sep 09 '16 at 12:31

4 Answers4

13

You have to place the const at the right place in the declaration. The rule is: const applies to the thing immediately to the left, unless it's at the left edge itself, when it applies to the right.

Therefore, these two are (mutable) pointers to a constant integer:

const int * p;
int const * p;

This is a constant pointer to a (mutable) integer:

int * const p;

And these are constant pointers to a constant integer:

const int * const p;
int const * const p;
Angew is no longer proud of SO
  • 167,307
  • 17
  • 350
  • 455
6

Solution

class CMyClass{};

class CSomeClass{
    static CMyClass* const IMPL;
};

CMyClass* const CSomeClass::IMPL = new CMyClass;

Explanation

const in C++ is not the exact analog of Java's final.

  • In Java the final specifier applies to the variable and means that the variable cannot be reassigned (though the object referred to by that variable can still be modified).

  • Unlike that, in C++ const applies to the type. Since C++ has pointers it is important to distinguish the type of the pointer variable itself and the type of the object to which that variable would refer. Depending on where you put your const it applies to the former or the latter. The other answers elaborate on that in more detail.

Leon
  • 31,443
  • 4
  • 72
  • 97
  • 3
    Could you add some comments......I don't think he understands that this could fix his problem, because he does not know what he is looking at – DarthRubik Sep 09 '16 at 12:18
5

1) Pointer to a const element: const T* ptr

2) Const pointer to a mutable element: T* const ptr

3) Const pointer to a const element: const T* const ptr

What you want here is 2) : const pointer to a mutable element.

giant_teapot
  • 707
  • 4
  • 15
0

C++'s 'final' is not related to constants, it's for virtual functions: it indicates a virtual function is the end of the line, and won't be overridden.

Use const_cast to ignore const and call a const method on the object:

const CMyClass* CSomeClass::IMPL = new CMyClass;
const_cast <CMyClass *> (CSomeClass::IMPL) -> someNonConstMethod ();

But this "feels" wrong; you're trying to protect your variable by making it constant, so overriding const doesn't seem like what you really want. Maybe:

  • Instead of protecting the variable with const, make member variables private so outsiders can't tinker with them. Then provide accessor functions (non-const) to allow them to be manipulated in allowable ways.
  • If you have member variables that need to be altered from const methods, mark them as 'mutable'.
  • To protect an object from being deleted outside your control, make its destructor private.
Perette
  • 821
  • 8
  • 17