开发者

In C++, is a const method returning a pointer to a non-const object considered bad practice?

In C++, is a const method returning a pointer to a non-const object considered bad practice? For example. consider the following methods:

// Makes perfect sense
b开发者_如何学Cool isActive() const { return m_isActive; }

// Makes perfect sense, both consts ensure nothing is modified
const SomeObject* someObject() const { return m_someObject; }

// Makes perfect sense, no const because SomeObject is mutable,
// thus MyClass is indirectly mutable
SomeObject* someObject() { return m_someObject; }

// Makes no sense, if you're just returning a pointer to a const object,
// then the method should clearly be const since nothing can be modified
const SomeObject* someObject() { return m_someObject; }

The last combination puzzles me: is the following considered bad practice?

SomeObject* someObject() const { return m_someObject; }

Because the class that method returns is not const, but the method is, it is somewhat pointless since you could modify SomeObject and thus indirectly modify your class... so is that form considered bad practice? e.g. should you only use one of the following in place of it?

const SomeObject* someObject() const { return m_someObject; }
SomeObject* someObject() { return m_someObject; }

Real-world situation: I'm writing a smartphone game which has a Game class. The Game class contains several methods which return pointers to utility classes like InputManager, AudioManager, etc.

class Game
{
public:
    InputManager* inputManager() const { return m_inputManager; }
    ...

private:
    InputManager* m_inputManager;
    ...
}

Does it make ANY sense at all to make inputManager() const, since the object it returns is not? (and should not be, since the InputManager needs to be mutable for its state to be updated, etc.)

Or should I remove the method's const modifier to more accurately reflect the method's behavior? That way if I had a const Game, I couldn't call inputManager() and then mess with the Game's input manager even though the Game was const.


It depends on whether the non-const pointer is pointing to something inside the const object, or whether it is newly allocated memory that is meant to be variable.

Consider something that returned a copy of a string; it's fine for the returned copy to be non-const, even if the original string is const. The ownership of the copy is being passed from the method to the calling code; ensuring that the copy is appropriately destructed is now the calling code's problem (quite possibly a very minor problem).

However, it would be a very bad idea to return a non-const pointer to something from inside a const object.


That's perfectly acceptable. A const method means that you're not modifying the object whose method you're calling - it does not say anything about any other objects. Of course, that object could be part of "this", or it could be "this" - but that's beyond the point.

"const" in general is more of a promise than anything, but the underlying idea is the same - a const method says that "this" is const, and that's about all.


In my opinion, returning a pointer of member is a bad idea, whether const or not.

When an object return a handle of its private member, others can change the private member through this handle. The state of object might be inconsistence and cause lots of trouble. Even if there is a const, caller still can use const cast to bypass this check. So it is not a good idea to return handle of any private member of object.


I don't think that const matter much here.

It's normally thrown upon to return a handle (pointer, reference) to an attribute:

  • it ties users to a particuler implementation, making it impossible to change it
  • it makes it impossible to enforce invariants (non-const versions), you may not have such now, but you never now what the future will give

If you begin making attributes directly accessible, they are as good as public.

Examples:

class Foo
{
public:
  std::vector<Bar> const& bars() const; // Ooops, impossible to move to a `deque`
                                        // or to enable polymorphic behavior
private:
  std::vector<Bar> mBars;
};

You're better off returning by value, this way if you change your internals you can always provide a new method and make some conversion in the old one not to break your interface (marking it deprecated and all).

Remember: people have been sent to jail for exposing their privates!


In your case, the Game and InputManager objects seem to be singletons. If this is the case, you only need to assure, that only one instance of Game (containing only one InputManager) exist, and skip const decorators. As suggested above, In this case, I would return a reference to the contained objects, no pointers.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜