For example:
struct B{};
struct A {
const B& findB() const { /* some non trivial code */ }
// B& findB() { /* the same non trivial code */ }
B& findB() {
const A& a = *this;
const B& b = a.findB();
return const_cast<B&>(b);
}
};
The thing is I want to avoid repeating the same logic inside the constant findB and non-constant findB member function.
If the function is non-constant, then the function is allowed to change values of the object on which it is being called. So the compiler doesn't allow to create this chance and prevent you to call a non-constant function on a constant object, as constant object means you cannot change anything of it anymore.
The statement int* c = const_cast<int>(b) returns a pointer c that refers to a without the const qualification of a . This process of using const_cast to remove the const qualification of an object is called casting away constness. Consequently the compiler does allow the function call f(c) .
The const qualifier explicitly declares a data object as something that cannot be changed. Its value is set at initialization. You cannot use const data objects in expressions requiring a modifiable lvalue. For example, a const data object cannot appear on the lefthand side of an assignment statement.
There are legitimate uses of having two member functions with the same name with one const and the other not, such as the begin and end iterator functions, which return non-const iterators on non-const objects, and const iterators on const objects, but if it's casting from const to do something, it smells like fish.
Yes, you can cast the object to const
, call the const
version, then cast the result to non-const
:
return const_cast<B&>(static_cast<const A*>(this)->findB());
Casting away const
is safe only when the object in question was not originally declared const
. Since you are in a non-const
member function, you can know this to be the case, but it depends on the implementation. Consider:
class A {
public:
A(int value) : value(value) {}
// Safe: const int -> const int&
const int& get() const {
return value;
}
// Clearly unsafe: const int -> int&
int& get() {
return const_cast<int&>(static_cast<const A*>(this)->get());
}
private:
const int value;
};
Generally speaking, my member functions are short, so the repetition is tolerable. You can sometimes factor the implementation into a private template member function and call that from both versions.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With