我如何让对象知道它在哪个容器中?
我需要一种方法来将各种物品放入集合中。 每个项目一次只能设置一个。 我还需要能够询问它所设置的项目。我有3个问题:
这是一个有效的实现?
如果我将这些类拆分为多个头文件,我该如何使用它,因为每个类都需要另一个类?
我可以在项目类中使用引用而不是指向Manager的指针(因为我不喜欢指针)?
class Manager {
public:
add_item(Item& item) {
items.insert(&item);
item.manager = this;
}
remove_item(Item& item) {
items.erase(&item);
item.manager = nullptr;
}
private:
std::unordered_set<Item*> items;
}
class Item {
public:
Manager* get_manager() {return manager;}
private:
Manager* manager;
}
这是一个有效的实现? 如果我将这些类拆分为多个头文件,我该如何使用它,因为每个类都需要另一个类?
你应该使用前向声明。
在一个好的面向对象设计中,对象不应该知道它是如何存储的。 它看起来像你的对象不应该负责需要本地化对象的活动。
std::unordered_list<Item*> items;
这是不正确的。 你想散列对象的地址吗?
我可以在项目类中使用引用而不是指向Manager的指针(因为我不喜欢指针)?
传递给函数时你总是可以用引用替换指针。 它没有问题。
我如何让对象知道它在哪个容器中?
你不应该需要在适当的课堂设计中这样做。 有些东西像依赖注入,但我认为这超出了你的实际需求。
这是一个有效的实现?
没有
如果我将这些类拆分为多个头文件,我该如何使用它,因为每个类都需要另一个类?
使用前向声明(查看更多细节)。
我可以在项目类中使用引用而不是指向Manager的指针(因为我不喜欢指针)?
你不能。
除了实际提出的问题之外,还有更深入的内容,最终似乎是一个设计问题,并且您要求解决XY问题。
你不喜欢(生)指针是一个非常好的胆量感觉,你的实际设计可能有什么问题。 那么,不幸的是,你不能使用像std::unordered_set
这样的标准容器来管理引用。
你可以做的是使用动态内存管理工具提供的智能指针。
您必须采取的主要决策是,像std::shared_pointer
, std::weak_ptr
或std::unique_ptr
这样的各种智能指针中的哪一个是正确管理必要所有权需求的正确语义正确。
Manager
也许不是你想要做的最好的命名选择。 请查看经典的设计模式,如果有更合适的东西从这些。
例如,听起来你需要类似Observer的东西,跟踪一些Item
变化/事件,并将它们转发给其他已注册的Item
实例。
由于Observer
不需要拥有任何已注册的Item
实例的所有权,因此std::weak_ptr
似乎是引用它们中的任何一个的正确选择。
我需要一种方法来将各种物品放入集合中。 每个项目一次只能设置一个。 我还需要能够询问它所设置的项目。我有3个问题:
这是一个有效的实现?
基本的想法是合理的,尽管它没有执行你的数据模型或防御有问题的场景。 有关您可以执行的操作的示例:
void add_item(Item& item) {
if (item.manager == this) return; // already owner
if (item.manager) // already has another owner...
item.manager->remove(item);
items.insert(&item);
item.manager = this;
}
如果我将这些类拆分为多个头文件,我该如何使用它,因为每个类都需要另一个类?
你为什么想要? 这些课程似乎太简单了,以至于没有任何需要,而这只会让事情变得复杂。 (正确的方法是使用前向声明标题。)
我可以在项目类中使用引用而不是指向Manager的指针(因为我不喜欢指针)?
不适用于你当前的设计,因为你的代码在从Manager
删除一个Item
之后将item.Manager
设置为nullptr
,这是一个合理的事情。
更一般的,你确实需要确保实际的Item
对象的生命周期在你存储指向Manager
对象的指针的时候。 这可能是也可能不是你写代码的方式的自然结果,或者通过调用item.manager->remove(item);
在Item
毁坏之前。
上一篇: How can I make an object know what container it is in?
下一篇: Understanding Inversion of Control and Dependency Injection