C++:管理一组对象,以便持有的对象可以访问持有它们的数据结构
我在链表中存储指向类Cell
的所有实例的指针。 std::list<Cell*> cells
存储在名为Game
的类中。方法Game::update()
迭代完成列表cells
中保存的所有Cell
实例,并调用每个单元的方法Cell::update()
。如果Cell::update()
方法在某个点发现该单元已准备好分割,则需要push_back()
指向新单元的指针到cells
,以便新单元可更新。 但是,如何才能在cell
内参考Game::cells
才能做到这一点?我曾考虑以下选项:C++:管理一组对象,以便持有的对象可以访问持有它们的数据结构
- 在全球范围内定义
std::list<Cell*> cells
代替。- 令人作呕,使得它不可能有一个以上的
Game
- 令人作呕,使得它不可能有一个以上的
- 制作
std::list<Cell*> cells
的Cell
- 比全局变量更好的静态成员,但仍避免使用多个
Game
实例
- 比全局变量更好的静态成员,但仍避免使用多个
- 将对当前游戏的
Game::cells
的引用作为参数传递给Cell的构造函数,并随后存储临时副本在新建成的小区实例- 我认为这是一个有点僵硬
- 传递到当前游戏的
Game::cells
的引用作为参数传递给Cell::update()
方法T参考
是否有更优雅解决方案利用?
我不会引入Cell
和Game
之间不必要的依赖性,如果所有Game
确实是调用Cell
的手法与持有它们的实例。
您可以改为从Cell::update()
返回新的Cell
(或无),并让Game
决定要做什么,最有可能将它们添加到列表中。您也可以在Cell
中为此定义一个新函数,如Cell::splitCell()
,并且让Cell::update()
只更新Cell
对象的属性(如名称所示)。
我可能会将Game
的引用传递给Cell::update()
,然后告诉Game对象分割单元格,但其他选项可能会更好,因为我仍然不认为我完全了解了您的总体目标是什么。
我不明白你的意思,为什么我要在Game :: update()中管理这个部门,而不是'Cell :: update()',如果我传递了一个对'Game'实例的引用? – jms
将参考Game
传递给Cell
构造函数。然后创建一个函数,让Cell
将其他Cell
对象推到列表上(或使Cell
为朋友类Game
,以便它可以直接访问列表)。
这样,Cell
可以决定它何时需要分割,但它可以将操作委托给它所属的对象Game
。
此外,如果有任何未来的事情Cell
可能想Game
这样做,他已经拥有了正确的对象。
如果Cell对象必须知道它们属于哪个Game对象,则从std :: list <>中派生一个类,并将一个指向Game(Game *)的指针作为Cell的成员。然后Cell对象可以使用这个指针向游戏添加另一个Cell。
class Game
{
class Cell
{
public:
Game *game;
};
class Cells : public std::list<Cell *>
{
Game *game;
operator += (Cell *cell) {cell->game = this->game; ....}
};
Cells cells;
};
从标准库容器类派生并不是最好的想法。你必须非常小心(即保护或私人派生),你可以引入内存泄漏,因为它们的析构函数不是虚拟的。 –
如果将派生类嵌入到对象中,则会调用正确的析构函数。 –
是的,如果您包含派生类已知的对象,则会调用正确的析构函数。如果你包含一个通过指向base的指针已知的对象(比如通过智能指针),那么就会调用错误的析构函数。我在设计界面时遵循的原则之一是:使其难以以不安全的方式使用。这样可以节省您和其他人在路上的时间。 –
刚刚从'Cell :: update()'返回需要的东西,然后让'Game'将新单元格推入列表中? – bbtrb
我认为,但如果细胞遭受奇怪的突变并决定分成4部分,我会返回什么? – jms
'std :: vector'将是一个简单而直接的解决方案。在这一点上,我不会担心很多性能问题,只是尝试分工并正确设计界面。 –
bbtrb
|