简体   繁体   中英

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.

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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM