0

Can someone suggest a better design for the situation where we want two objects to "talk" to each other through a const intermediate.

Here is a contrived example, where two players trade lemons. A player finds another player in the "world", but the "world" should be const, since a player shouldn't be able to modify it (lets say by deleting walls).

void Player::give_lemon()
{
    const World& world = this->get_world();

    const Player& other = world.get_nearest_player(*this);

    this->lemons--;
    other.lemons++; // error
}

What designs do people use, a simple const_cast is easy but dirty. Or we could provide some way of "looking up" a non-const Player reference, lets say by having access to a non-const player_list() but here we'd be duplicating functionality already available in World, possibly less efficiently, all for a round-about way of doing a specific const_cast.

c z
  • 7,726
  • 3
  • 46
  • 59
  • I imagine, you might want to make Players `mutable` inside your World and return non-const reference to them. – SergeyA Jan 07 '16 at 16:59
  • It seems to me that if the world conceptually contains players then changing the state of a player changes the state of the world. I can't think of an example of what you are trying to. It seems to me that you want to make some functions *callable* (changing players) but not others. So in what contexts can the other functions be called? Maybe your design might be better organized by having the world implement several different *interface classes* each appropriate in different contexts? Then rather than passing a reference to the world, pass a reference to whatever *interface class* is relevant – Galik Jan 07 '16 at 17:12
  • 1
    `const` is incorrect in this context because you *are* changing the state of those objects. – Joel Cornett Jan 07 '16 at 17:13

2 Answers2

1

The most direct solution is to make world.get_nearest_player() return a Player&, not a const Player&.

1

It seems that both Player and World can be seen as actors

World happens to be const

Introduce a Manager class that handles both:

Manager would take a const World in its constructor and then Players can be added or removed.

void Player::give_lemon()
{
    Manager& mgr = this->get_manager();

    Player& other = mgr.get_nearest_player(*this);

    this->lemons--;
    other.lemons++; // error
}

The manager then keeps track of positions of players in its world. World is const and cannot have a mutable list of players, the manager can.

Glenn Teitelbaum
  • 10,108
  • 3
  • 36
  • 80
  • I think this is more appropriate, since I think the root issue is that your 'world' might need to be conceptually two different things. Because your 'game board' you might want const, but the "players' state" obviously needs to change. If you don't want players to cheat, then you need to have this 'manager' (similar to game master) be allowed to change the players' states (such as lemons++/--) – mawalker Jan 07 '16 at 17:54