【问题标题】:Design pattern for accessing non-const through a const intermediate通过 const 中间访问非 const 的设计模式
【发布时间】:2016-01-07 16:45:43
【问题描述】:

对于我们希望两个对象通过const 中间体“对话”的情况,有人可以提出更好的设计吗?

这是一个人为的例子,两个玩家交换柠檬。 玩家在“世界”中找到另一个玩家,但“世界”应该是const,因为玩家不应该能够修改它(比如说删除墙)。

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

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

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

人们使用什么设计,简单的const_cast 简单但肮脏。 或者我们可以提供某种“查找”非常量 Player 引用的方式,比如说可以访问非常量 player_list(),但在这里我们将复制 World 中已有的功能,可能效率较低,所有这些都是为了做一个特定的const_cast

【问题讨论】:

  • 我想,您可能希望在您的 World 中创建 Players mutable 并返回对它们的非常量引用。
  • 在我看来,如果世界在概念上包含玩家,那么改变玩家的状态就会改变世界的状态。我想不出你想要做什么的例子。在我看来,你想让一些函数callable(改变玩家)而不是其他的。那么在什么情况下可以调用其他函数呢?也许你的设计可以通过让世界实现几个不同的接口类来更好地组织,每个类都适用于不同的上下文?然后,与其传递对世界的引用,不如传递对任何相关的接口类的引用
  • const 在这种情况下不正确,因为您正在更改这些对象的状态。

标签: c++ design-patterns constants const-cast


【解决方案1】:

看来PlayerWorld都可以看成演员

World恰好是const

引入一个同时处理两者的Manager 类:

Manager 将在其构造函数中使用const World,然后可以添加或删除Players。

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

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

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

然后,经理会跟踪玩家在其世界中的位置。 Worldconst 不能有一个可变的球员名单,经理可以。

【讨论】:

  • 我认为这更合适,因为我认为根本问题是你的“世界”可能需要在概念上是两个不同的东西。因为您的“游戏板”可能需要 const,但“玩家状态”显然需要改变。如果你不想让玩家作弊,那么你需要让这个“经理”(类似于游戏大师)被允许改变玩家的状态(例如柠檬++/-)
【解决方案2】:

最直接的解决方案是让world.get_nearest_player() 返回Player&,而不是const Player&

【讨论】:

  • 如果 Player 是世界的一员(我想是的),这将是不可能的。
  • 我宁愿假设std::vector<std::unique_ptr<Player>> - 但是是的。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多