c ++ OOP设计 - 将数据成员传递给其他类 - 这是否合理?

时间:2013-01-28 21:41:10

标签: c++

我还有一个问题希望能够总结我的想法。

假设我有以下3个类:

类玩家:

class Player {
private:
    int positionX, positionY;
public:
    void move(Board& b) {
      // player changes its position on the board(move)
      b.removeCharFromBoard(positionX, positionY);
      positionX++;
      positionY++;
      // 'P' indicates a Player in the Board....
      b.insertCharToBoard(positionX, positionY, 'P');
    }
};

班主席:

class Board {
private:
    // BOARD_C and BOARD_R are both "#define ..." for some integer number.
    char board[BOARD_C][BOARD_R];
};

类GameEngine:

class GameEngine {
private:
     Board* board;
public:
     void playTurn(const Player& p) {
        p.move(board);
     }
};

你认为GameBoard的playTurn函数会用参数“board”调用Player的移动功能似乎是合理的吗? 我需要这样做才能在棋盘数据成员中标记玩家已经改变了他的位置。 它是否遵守OOP基本规则?

谢谢大家, 聚合者!

4 个答案:

答案 0 :(得分:4)

是的,在这种情况下它似乎是合理的(在这种情况下,“我的意思是”考虑我可以猜到的GameEngine和{{1}的语义}类及其关联/聚合关系的性质“):

  1. 而是使用智能指针而不是原始指针来保存Board中的Board对象。在这种情况下,GameEngine可能就是您想要的,因为所有其他别名似乎只是观察者,并且板对象的生命周期绑定到unique_ptr对象的生命周期。但是,如果需要共享所有权,请选择GameEngine。尽量不要使用原始指针shared_ptrnew,因为它们会导致错误的代码;
  2. 您仍然需要在delete类的接口上提供公共函数来修改电路板,因为Board将无法访问其私有成员变量(和Player碰巧是一个。)。
  3. 而不是board s,使用#define值来表示电路板的大小(如果您使用的是C ++ 11)。您可能还需要考虑Boost.MultiArray来创建安全二维C风格数组。

答案 1 :(得分:3)

你的方法很好。 GameEngine将被用作游戏的某种控制器。多亏了它你可以过滤玩家的动作,检查这种移动是否可行,或者在特定玩家操作的情况下做其他类型的动作。

其次,对于这个解决方案,您不必将播放器连接到特定的电路板,这扩展了您在其他选项之间的可能性,例如在电路板之间轻松转移播放器。我认为你的方式很好:)

答案 2 :(得分:1)

您必须考虑应用程序的更改方式以及您希望引入的功能。从这段代码看起来它看起来不错,但是当你引入新功能时它会是什么样子?

其他解决方案是将播放器仅移动逻辑,它将更新其位置,然后您的GameEngine将根据您所有玩家的当前位置更新电路板条目。想象一段时间你会想要实现碰撞检测,然后在每个玩家更新其位置或移动之后,将发生碰撞检测并纠正这些移动,并且只有在你的板上稍后才能正确更新。

答案 3 :(得分:1)

已经说了很多话,但如果我可以添加一些东西。

Board(无论是private还是Player)传递给void Sprite::draw(RenderTarget& target, RenderStates states) const { if (m_texture) { states.transform *= getTransform(); states.texture = m_texture; target.draw(m_vertices, 4, Quads, states); } } 并不是本身,并且这种设计用于多种架构(代码取自SFML 2.0):

RenderTarget

Board是您的Board。这里要理解的是,您将仅使用其公共接口(您有权访问)在draw() 上运行。在上面的代码中,targetPlayer上用来强制它绘制内容的方法。

将内部对象传递给更高级别类(如Board)的整个想法可以解释为bridge OO pattern,其中可以有几个接口IBoardManipulator的实现和几个类可以实现GameEngine(或类似的东西)。

那就是说,我会说遵循游戏引擎的总体思路要好得多:

  1. 注册游戏的实体(在这种情况下是玩家)
  2. 捕捉播放器输入
  3. 摘要&对玩家输入作出反应(请求移动玩家)
  4. 处理游戏逻辑(检查玩家是否可以移动到指定位置,如果是 - 移动他)
  5. 每个注册实体draw()都会调用Board作为实体可以使用的目标Player
  6. 从第2步开始重复
  7. 我并不是说对于一个简单的架构来说这是必需的,但是在更长的运行中,管理起来比处理每个Board的讨厌的事情要容易得多 - 类可以对{{1}}进行。