const and no const methods in c++? - 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.

Related

How to use the non-const getter if there's a const one too?

If I have a class with getters of return type both const and non-const, how can I use the non-const one?
The class (MeshManipulator.h):
namespace vortex::meshSculptEngine
{
class MeshManipulator
{
public:
...
topologyMesh::Mesh* getMesh();
const topologyMesh::Mesh* getMesh() const;
...
};
}
The code where I want to use the Mesh (SimpleMeshCorrector.cpp):
void SimpleMeshCorrector::smoothBoundaryLoops(float distance)
{
if (!_boundaryLoops.empty()) {
Mesh* mesh = getEngine()->getManipulator()->getMesh();
...
}
}
I get the following error:
A value of type "const vortex::topologyMesh::Mesh*" cannot be used to
initialize an entity of type "vortex::topologyMesh::Mesh*"
I can use const_cast but I just don't feel that this is the correct way to solve this problem.
Root cause is (as clarified in comments) that getManipulator() returns a const MeshManipulator*. On a const object, only methods declared const can be called. Thus, the const getter is always called and never the non-const version.
Depending on the context, there are three ways to go on:
Use (or write) a method that returns a mutable MeshManipulator*.
Copy the const Mesh* to a local, mutable object.
Use const_cast<Mesh*> to be able to mutate the object in place. This, however, defeats the purpose of constness. What's more, if the object pointed to was declared const this will result in undefined behavior. So use with care.

Purpose of overloading member function returning iterator and const_iterator

In my class assignment I am suppose to implement member functions of a predefined class. I am confused on the purpose of these the overload on findStudent. Can this class not be designed to only contain one definition, which returns a regular iterator that can be casted as const? Or rather, use std::find since it is already overloaded to return a const_iterator?
class Class{
public:
Class(std::string name, std::string teacher, std::string capacity);
std::string getTeacher();
std::string getName();
int getCapacity();
void addStudent(std::string);
void removeStudent(std::string);
std::vector<std::string>::iterator findStudent();
std::vector<std::string>::const_iterator findStudent() const;
private:
std::string name;
std::string teacher;
int capacity;
std::vector<std::string> students;
};
The purpose of overloading those functions is that they differ by their const-ness.
Consider:
you pass Class foo; to a function
void bar(Class& foo).
If inside this function you were to call findStudent(), the non-const version of the member function would be invoked. As a result, you would get a mutating iterator of std::vector<std::string>. The iterator would allow to assign new values, clear strings and do whatever else you want with the values.
Now consider another case:
void bar(const Class& foo).
Inside this function, the const version of findStudents() will be called, and you won't be able to modify the values. You will be able to inspect them, to print them, to sum the lengths, i.e., you will be able to do only non-mutating operations on your students.
The purpose of this is to enable both the compiler and -- especially important! -- the programmer to reason about the code. Const functions do not change the state of the object, they conserve invariants of the code. For instance, it generally holds that if you call a const function twice in succession, both calls should return the same answer. (This holds "generally", but not always, especially if we are dealing with hardware).
When a member function is const-qualified, it can be called on a const object. (It can also be called on a non-const object, since a const conversion that ADDs const is a valid implicit conversion.)
Member functions that are not const qualified can only be called on non-const objects (because they can change the state of the object, defeating the meaning of const if such a conversion could happen.)
Thus:
class Foo {
public:
...
int& operator[](int idx) { return values[idx]; } // 1
int operator[](int idx) const { return values[idx]; } // 2
private:
int values[10];
};
We have two versions of operator[], one returning a mutable reference, and the other returning a copy (on which changes won't affect the object it came from.
And so
Foo f;
int& x = f[3]; // calls 1, since f is non-const
const Foo cf;
int y = cf[3]; // calls 2, since cf is const
If you want your code to work on const and non-const objects, but always return a const_iterator, then you could get by with only implementing a version of findStudent that has the const qualification, like op 2 does above, and not overload it with the non-const version.
I am guessing that findStudent is supposed to take a name (or other criteria) and return an iterator to that student, or an "end" iterator if it's not found. In that case, you'd use std::find() in the implementation of find_student. So be sure to allow callers to say what student they want to find!

How to define a final variable (mutable constant) in 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.

Return type for a vector

I have a ClassA that has a private: vector<ClassB> vec. I'm filling the vector up in ClassA::fillVec().
Now i'd like to return the vector(by reference? so no copying) and i'd also like forbid any further changes using const.
What still confuses me is the syntax. What i have so far is
const std::vector<ClassB> &ClassA::fillVec(...) const {}
But I don't know if that is right. And even if it's right, I found this solution on the internet, so if anyone could explain why the two const
The first const means that the return type is const reference i.e. the vector may not be modified through the reference.
The const at the end means that the member function is not allowed to modify the (ClassA) object. It is therefore allowed to call that method on a const ClassA instance. This of course contradicts with the purpose of the function assuming it's supposed to modify the member; it should therefore not be const.
You want to return a const reference to prevent the user changing it; but the function itself can't be const, since it modifies a class member.
const std::vector<ClassB> &fillVec(<parameters>);
^ ^
const return value no const here
You would use the second const on member functions that aren't supposed to modify the object they're called on.

C++ const in getter

I'm still learning about C++ and I'm reading everywhere that I have to use const everywhere I can (for speed reason I think).
I'm usually write my getter method like this:
const bool isReady() {
return ready;
}
But I've seen that some IDE autogenerate getter in this way:
bool getReady() const {
return ready;
}
But, writing delegates, it happened to me to find this error if the const is after the function:
member function 'isReady' not viable: 'this' argument has type 'const VideoReader', but function is not marked const
So that, what is the better way to write a const getter? Do I really have to care about?
There is a huge difference between the two ways.
const bool isReady()
The code above will return a const bool, but it does not guarantee that the object will not change its logic state.
bool isReady() const
This will return a bool, and it guarantees that the logic state of your object will not change. In this case it is not necessary to write const in front of the return type. It makes no sense to return a const bool because it is a copy anyway. So making it const is useless. The second const is needed for const correctness, which is not used for speed reasons but to make your program more reliable and safe.
They mean two differnt things:
const bool isReady() {
return ready;
}
This returns a constant bool. Meaning a bool which cannot change value from the time it's been created.
bool getReady() const {
return ready;
}
This is a a constant function, meaning a function that will not alter any member variables of the class it belongs to. This is the style recommended to use for getters, since their only purpose is to retrieve data and should not modify anything in the process.
const method informs compiler that you will not modify class instance on which this method is called:
class A {
public:
bool getReady() const {
return ready;
}
};
so if you try to modify your object inside getReady() then compiler will issue error. Const methods are usefull where you have ie.: const A&, or const A*, then you can call only const methods on such objects.
as for:
const bool isReady() {
return ready;
}
this const provides actually no real benefit, because bool is copied while isReady() returns. Such const whould make sense if returned type was a const char* or const A&, in such cases const makes your char string or A class instance immutable.
A const getter has the signature
bool getReady() const
The other version isn't a const method, it just returns a const value (which is basically useless).
Having a const getter allows you to call it on const objects:
const Object obj;
obj.getReady();
This is only valid if getReady is marked as const.
There is a difference between using the const keyword for the return type or for the method signature. In the first case the returned value will be a constant value. In the second case the method will be a so-called constant method, which cannot change the representation of the object. On constant objects, only the constant methods are callable.