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.
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.
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 technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.