How to define a final variable (mutable constant) in C++? - c++

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++?

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;

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.

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.

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.

Related

c++ const member function returning reference to class member

If I have the class member function:
bar* foo::get_value() const
{
return &_value;
}
the compiler will complain
cannot initialize a variable of type bar * with an rvalue of type const bar *
_value is not const in the class.
If I have the function:
bar* foo::get_value() const
{
return const_cast<bar *>(&_value);
}
It works just fine.
I thought that declaring a member function constant meant that you promise to not modify the internal contents of the class, but the operation & seems to return a constant pointer in const member functions. Why is this?
When you declare a function const, you are saying that this is a function that is permitted on both a non-const and const instance of the object. Because it can be invoked on a const instance, the function should not mutate the object. When you return a non-const reference to an internal object, you are providing the caller with a way of mutating the object's internal state indirectly. To fix this, return a constant object, instead.
In other words, instead of:
Bar* Foo::GetBar() const
Do:
const Bar* Foo::GetBar() const
Or, better yet:
const Bar& Foo::GetBar() const
As you've observed, const_cast allows you to undermine the const-ness of the object. In general, you should avoid using const_cast; using it is a code smell, and it undermines the intended const gurantees.
When an object instance is declared const, it's treated as if all its member variables were also const -- that is, except members which have been declared with the keyword mutable.
So, theoretically, you could declare _value as mutable, which would at least be slightly preferable to const_cast<>-ing your way round it. But it's still not ideal. The right way to do this is to provide two overloads:
const bar* foo::get_value() const
{
return _value;
}
bar* foo::get_value()
{
return _value;
}
(and better yet would be to use references or smart pointers rather than raw pointers).
The problem is the return type of the getter function. You are returning bar* instead of const bar*. The former would allow the caller of the get_value function to modify the object. But that's explicitly forbidden by your declaration of _value as const.
You can bypass that with const_cast, but it's incorrect. It's like telling the compiler "trust me, I know what I'm doing", but in this case, you don't. You have no control over what the calling code will do with the object. And if they try to modify it—bam, undefined behavior.
Make life simple on yourself, just make the getter return const bar*:
const bar* foo::get_value() const
{
return &_value;
}
Do note that the compiler error message essentially told you the change you need to make to your code.
A const member function works only on a const object. With a const object you cannot change its member variables. That is why the compiler does not allow you to make a non const pointer to a member variable of a const object.

Do class member reference variables have in-built "const-correctness"?

struct A {
int &r;
A (int &i) : r(i) {}
void foo () const {
r = 5; // <--- ok
}
};
The compiler doesn't generate any error at r = 5;.
Does it mean that &r is already const-correct being a reference (logical equivalent of int* const) ? [Here is one related question.]
I'm not sure exactly what you mean by "already const-correct", but:
Assigning to r is the same as assigning to whatever thing was passed into the constructor of A. You're not modifying anything in the instance of A when you do this, so the fact that foo is declared const isn't an obstacle. It's very much as if you'd done this:
struct A {
int * r;
A (int * i) : r(i) {}
void foo () const { *r = 5; }
}
The fact that foo is const means that it doesn't modify anything in the A instance it's called on. There's no conflict between that and having it modify other data it was supplied with.
Of course if you happened to arrange for r to be a reference to some member of A then calling foo would modify the instance of A after all. The compiler can't catch all possible ways in which constness of a member function might be violated; when you declare a member function const you're promising that it doesn't engage in any such subterfuge.
Yes, it's the logical equivalent of int* const.
You may want to create and use appropriately qualified accessors in this case to prevent unwanted alterations to the value r references.
I interpret a const member function as implicitly inserting const just to the left of every data member that doesn't already have such a qualifier. That const is already there implicitly for references (int & const r; is illegal syntax). In other words, references are "already const-correct" to use your nomenclature.
It would be nice if the const qualifier on a member function had the affect of inserting const in every possible valid position for every data member (e.g., data member int ** foo; acts like int const * const * const foo; in a const member function), but that isn't what happens, and it isn't what the standard says will happen.

Can const member function return a non-const pointer to a data member?

Code goes first:
class A
{
public:
...
int *foo() const
{
return _px;
}
private:
int *_px;
}
The member function foo returns a non-const pointer to private member _px, which, I think, opens a door to modifying member _px, right?
Is foo a const member function? Should I add a const in front of the return type?
UPDATE
What a const-member-function should guarantee is that, it cannot change any data-member, right?
In my case, function foo doesn't open a door to modifying class As data-member _px, but a door to modifying what _px pointing to, So my question is, does this violate what a const-function should guarantee?
A const member function can only return a const pointer or reference to a member.
However, your example isn't returning a pointer to a member; it's returning a copy of a member that happens to be a pointer. That is allowed in a const member function (even if the pointer happens to point to another member).
This would not be allowed (note that it's now returning a reference):
int *& foo() const {return _px;}
but this would (returning a const reference):
int * const & foo() const {return _px;}
int *_px becomes int *const _px inside a const member function this implies that the pointer cannot be reseated but the data pointed to is still modifyable. Further your function returns a copy of the pointer so it does not matter anyways.
It does not open a door to modifying _px but rather what _px points to. It's up to you to decide whether you want to allow this or not.
For example, an iterator::operator-> would return a non-const pointer and const_iterator::operator-> would return a const pointer. Both methods can be const themselves.
Yes, for your case it can. However, it's generally advised to not to do this, because it allows changing constant objects:
void f(const A& a)
{
*(a.foo()) = 42; // damn!
}
Yes, for example see the std::streambuf pointers:
protected:
char* pbase() const;
char* pptr() const;
char* epptr() const;
http://en.cppreference.com/w/cpp/io/basic_streambuf/pptr

C++ const member functions are modifying member variables

Today I found out that code like that works. That sounds really strange to me, because as far as I always knew you can't modify any of members from const member function. You actually can't do it directly, but you can call non-const member function. if you mark member function as const that means that this pointer passed to the function is pointing to const object, then how non-const member function is called in the example bellow?
#include <iostream>
class X
{
public:
void foo() const
{
ptr->bar();
}
void bar() {}
private:
X * ptr;
};
int main()
{
}
Your member variable is not X, but pointer to X. As long as foo does not modify the pointer, it can be const.
When you have a pointer member, then the pointer is const in a const method. You won't be allowed to change the address stored in the pointer. But you can change the pointee all you like.
It's the difference between
X* const cannot_change_pointer; //this is how top-level const applies to pointers
const X* cannot_change_pointee;
What's even more interesting is that const on a method has no effect whatsoever on reference members for the same reason (a const method would only prevent you making a reference refer to something else which can't be done with a reference anyway).
That's seems perfectly OK. The call to foo does not modify the ptr member. Hence, the constness of foo is respected.
my 2 cents

const and no const methods in c++?

I have a program and many of its classes have some operators and methods with the keyword const like the followings:
operator const char* () const;
operator char* ();
void Save(const char *name) const;
void Load(const char *name);
First: what does it mean const at the end of the method declaration?, is it the same like putting it at the beginning?
Second: Why would be a const version and a no const version of operator() needed?
Thanks in advance.
First: what does it mean const at the end of the method declaration?, is it the same like putting it at the beginning?
No. A const at the end means that the method may be called on objects that are declared const. A const at the beginning means that the returned value is const.
Second: Why would be a const version and a no const version of operator() needed?
The non-const version returns a char* which is not const. By modifying this char* you could then in fact modify the object (assuming the char* is a member of the object).
Since this is not allowed for const objects, there's an overload of operator() for const objects, so that a const char* is returned, so the object can't be modified through it.
'const' at the end tells the compiler that this method does not change any member variables - that it is safe to call this method on const instances. So, Save could be called on a const instance, since it won't change that instance. Load on the other hand, will change the instance so can't be used on const instances.
The const version of operator() passes back a const pointer, guaranteeing the buffer passed back won't change. Presumably that's a pointer into a instance variable of the class. For non-const instances, the other operator() passes back a non-const pointer. It would have to be a pointer to some memory that even if written to, wouldn't change the contents of the instance.
Also, look up the 'mutable' keyword sometime. Understanding that will help you understand this idea of const-correctness.
Member function constness. It means the function can not(*) modify any of your member variables. It's like putting a const in front of all your member variables for this one function call. It's a good guarantee for the clients of your class and may also aid in compiler optimisations.
(*) - see also the keyword mutable.
Putting const at the end of a method declaration is stating that the object itself, or this, is const instead of the return type.
C++ allows methods to be overloaded on const for complicated reasons. Not enough space to go into full detail here. But here are a couple of short ones.
Ocassionally there is value, or flat necessity, in having a method behave differently when it is called from a const type. The most straight forward example is when you want to return a const value from a const method and a non-const value from a normal method.
Whether or not this is const dramatically changes the binding of the internal method. To the point that it would essentially become two different method bodies. Hence it makes sense to break it up into 2 different methods.
One note in addition to the other answers: there is no operator() in your example.
operator const char* () const;
operator char* ();
are conversion operators, which mean that objects of the class can be implicitly converted to C-style strings, like
void f(const MyClass& x, MyClass& y) {
const char* x_str = x;
char* y_str = y;
}
A declaration and usage of operator(), which means you can use an object of the class type sort of like a function, would look like:
class MyClass {
public:
const char* operator() (int x, int y) const;
// ...
};
void g(const MyClass& obj) {
const char* result = obj(3, 4);
}
If you're looking for a great resource on C++ (including tips on using const correctly) try "Effective C++".
A useful site about this: JRiddel.org
In C++ when you declare a method const by putting it AFTER the method signature you are asserting that "This method will not change any non-mutable instance variables in the object it is being called on."
The const before the return value (e.g. the const in: operator const char*...") is declaring that it only returns a variable pointer to a const char*. (You may not change the contents of the char* but you can re-assign the pointer.) If you wrote "const char* const ..." it would be a constant pointer to constant characters. (The const comes after the star).
The multiple versions are useful so the compiler can understand this:
const char* my_const_var = <object_name>();
char* my_var = <object_name>();
Chris
You should refer to the "HIGH·INTEGRITY C++ CODING STANDARD MANUAL" for knowing when it is recommended to use the const modifier for class members:
High Integrity CPP Rule 3.1.8: Declare 'const' any class member function that does not modify the externally visible state of the object. (QACPP 4211, 4214)
Justification: Although the language enforces bitwise const correctness, const correctness should be thought of as logical, not bitwise. A member function should be declared const if it is impossible for a client to determine whether the object has changed as a result of calling that function. The 'mutable' keyword can be used to declare member data which can be modified in const functions, this should only be used where the member data does not affect the externally visible state of the object.
class C
{
public:
const C& foo() { return * this; } // should be declared const
const int& getData() { return m_i; } // should be declared const
int bar() const { return m_mi; } // ok to declare const
private:
int m_i;
mutable int m_mi;
};
Reference Effective C++ Item 21;Industrial Strength C++ 7.13;
Const at the beginning applies to the return value. Const at the end applies to the method itself. When you declare a method as "const" you are saying that you have no intention of modifying any of the member variables of the class in the method. The compiler will even do some basic checks to make sure that the method doesn't modify member variables. The const in the return value prevents the caller from modifying the value that is returned. This can be useful when you return pointers or references to data managed by the class. This is often done to avoid returning copies of complex data which could be expensive at run time.
The reason you have two different operators is that the "const" version returns a const pointer to what is probably data internal to the class. If the instance of the class is const, then chances are you want the data being return should also be const. The "non-const" version just provides a method that returns a modifiable return value when the caller has a non-const instance of the class.