C++ const in getter - c++

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.

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.

How to define const getters that trigger a calculation?

I have a class which contains a data member that occasionally needs to be recalculated, though it is likely to be accessed multiple times before a recalculation is needed.
I have defined both const and non-const getter methods for the data, and within the getter method I would like to check whether or not the calculation needs to be run, and call the appropriate method if it does.
In the non-const getter, I check whether the value is up-to-date, and if not run the calculation before returning the data. Doing the same in the const getter caused the compiler to complain about the this object being a const type while the calculation method is non-const. I was therefore surprised that the code compiles if I simply call the non-const getter within the const getter. Could someone please explain why this works, because I am slightly confused.
class A {
bool isUpToDate=false;
double someData=0;
// Do some calculation
void calcData()
{
someData = doSomeCalc();
isUpToDate = true; // data is now up-to-date
}
// non-const getter
double& data()
{
if(!isUpToDate)
{
// run the calculation only if data is not up-to-date
calcData()
}
return someData;
}
// const getter that doesn't work
const double& data() const
{
if(!isUpToDate)
{
calcData() // compiler error: "this object is type const A but
calcData is non-const"
}
return someData;
}
// const getter that (mysteriously) works
const double& data() const
{
return data(); // why doesn't the compiler complain that data() is non-const?
}
I am sure that this behavior is actually reasonable and well-defined, I am just curious why it works because I don't understand what is happening here. I am using g++ as my compiler with the c++11 standard, in case that is a relevant factor in why this works.
You're not calling the non-const getter; you're calling yourself:
const double& data() const
{
return data();
}
is infinite recursion.
Because of data() const, *this is effectively const within the method. The call data() is equivalent to this->data(). Because this is a const A *, this selects the const getter again.
I was therefore surprised that the code compiles
Sure it compiles, but it doesn't actually work. It will either go into an infinite loop and hang or just crash.
In this scenario, you can declare someData and isUpToDate as being mutable. That means they can be modified even from a const member function. Then make calcData() be const, so that it can be called from another const member function.
Such an approach will often be eyed with suspicion! I use it for mutexes and for caches. I worry that yours might be perhaps slightly too much for this.
Do you really need data() to be const? You should make sure…
Make that field mutable, and use an update function:
bool updateNeeded;
double getNewValue();
class MyResource {
mutable double someData = 0.0;
void update() const {
// Because someData is mutable, this works fine
if(updateNeeded()) {
someData = getNewValue();
}
}
public:
double& getData() {
update();
return someData;
}
double const& getData() const {
update();
return someData;
}
};
When you have a member function like const double& data() const, all functions called by data must also be const, and not modify the object. For those that stumble onto this: Meaning of 'const' last in a function declaration of a class?
There are some ways to solve this:
You can change void calcData() to void calcData() const this will tell the compiler that the calculation method is const. This won't work here because your are assigning the result so it is non-const (it modifies member variables) so the compiler will yell at you.
You can change double const& getData() const to double const& getData(). But this will not work if you need A to be const sometimes.
Another solution is
class A {
bool isUpToDate=false;
double someData=0;
double& data()
{
if(!isUpToDate)
{
// run the calculation only if data is not up-to-date
someData = doSomeCalc();
isUpToDate = true;
}
return someData;
}
double data() const // Don't change anything, just return by value
{
if(!isUpToDate)
{
return doSomeCalc();
}
return someData;
}
}
This will return by value and re-calculate everything. The disadvantage is that it may be bad performance-wise if doSomeCalc() is intensive, since it needs to call it every time and cannot update someData.
Other answers have already mentioned using the mutable qualifier for someData (and isUpToDate). This will work fine, but some may be averse to using the mutable keyword, as they are usually used for specific purposes and can be dangerous if handled poorly.

Understanding const_cast in C++

I am trying to to understand const_cast.
In the example below, items_ is a private member variable.
The method getItems() is a const method, which means that it cannot modify the member variable items_.
getItems() returns a const vector reference which means that you cannot modify the member variable items_.
My question is, is const_cast necessary here? I don't think so as I don't need to cast away constness?
#include <iostream>
class test {
std::vector<Item> items_;
public:
const std::vector<Item>& getItems() const;
};
const std::vector<mv::Item>& mv::Workloads::getItems() const
{
return const_cast<std::vector<Item>&>(items_);
}
It is not only unnecessary but it is plain wrong in that place.
Consider what happens when you remove the const from the return type:
/*const*/ std::vector<mv::Item>& mv::Workloads::getItems() const
{
return const_cast<std::vector<Item>&>(items_);
}
Now the method returns a non-const reference to a const object! Note that the method itself is declared as const, hence this is const in the context of this method and also items_ is const. Using the reference returned by that method would lead to undefined behaviour when the method is called on a const test instance.
In that sense, the only effect of the const_cast here is to potentially silence an important compiler error should you ever decide to change the return type.
On the other hand, in the method as is (ie returning a const reference) there is no reason for the cast. items_ is const and a const reference to it is returned.
const_cast is useful eg to avoid code duplication for const and non-const methods when you do know for sure that the object you cast const away really is not const, see here for details.
PS: in case you actually do want to return a mutable reference to a member from a const method, you would declare the member mutable. Also then no const_cast would be required. Though, mutable should be used with care and usually isnt needed in the first place.
It is not neccessary, simply return the _items.
Const member functions see the the object itself (*this) as const, so every data member is seen as const, from which building and returning const reference is allowed.
#include <iostream>
using namespace std;
class test {
std::vector<Item> items_;
public:
const std::vector<Item>& getItems() const;
};
const std::vector<mv::Item>& mv::Workloads::getItems() const
{
return items_;
}

How to call a no-const function within a const override function in C++ [duplicate]

This question already has answers here:
How do I remove code duplication between similar const and non-const member functions?
(21 answers)
Closed 9 years ago.
There's a class below
class A
{
public:
string& getStr()
{
// Do a lot of work to get str
return str
}
const string& getStr() const;
};
Can I call the first function within the second function? I want to do this, because the second function have a lot of code in common with the first one. It cannot be like this:
const string& A::getStr() const
{
// Wrong
A temp;
return temp.getStr();
}
because there is added a new temp and the inner status between *this and temp is different (*this != temp).
Can it be called like I described?
As mentioned in How do I remove code duplication between similar const and non-const member functions?, the solution to avoid code duplication would be to put logic in the const method (assuming you do not need to modify object state or member that you modify is mutable) and call a const method from non const one:
class A
{
public:
string& getStr()
{
return const_cast<string&>( static_cast<const A *>( this )->getStr() );
}
const string& getStr() const {
// Do a lot of work to get str
return str
}
};
By making a method const you are making a promise (loosely) to the consumer that the method will not make any changes to the object. If your non-const version makes changes to the object then it cannot be called in the const method. It doesn't matter whether or not the current object is const or not. If your non-const method does not make changes to the object, then make it const.
getStr() const cannot call getStr() (non-const).
const functions can be called by non-const functions, however. Happens all the time. This is because a const function can only be called with a const this pointer. In a non-const function, the this pointer is also non-const, but it can be easily cast to a const pointer. The reverse is not true -- you can't (easily/correctly) cast away the constness of a const pointer. So from within a nonconst method you can call other, const methods.
The function getStr in your class A returns a reference of a local variable. What's more, it is the same question to the second function.

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.