【发布时间】:2020-08-14 15:36:02
【问题描述】:
我不明白当死对象是从不同的范围创建并放置到另一个范围的某种容器中时,如何防止访问它。示例
#include <iostream>
#include <string>
#include <vector>
class Foo {
public:
void Speak(){
std::cout << "ruff";
}
};
int main()
{
std::vector<Foo*> foos;
{
Foo foo;
foos.push_back(&foo);
// foo is now dead
}
for(size_t i = 0; i < foos.size(); i++){
// uh oh
foos[i]->Speak();
}
}
我已经尝试了大约 2 天来找出某种“共享”指针系统,它将Foo* 与另一个对象包装起来,但无论如何,它总是归结为这样一个事实,即使是“共享”指针不知道Foo 何时死亡。就好像我在寻找Foo 析构函数回调一样。
注意事项:C++ 98,无提升。
如果这个问题已经解决了 1000 次,我很想知道它背后的想法,以便我可以做出解释。
编辑:添加更多上下文
基本上我的设计中有这个反复出现的问题。我真的很喜欢“松散耦合”并将模块分开。但为了实现这一点,必须至少有一个地方可以连接它们。所以我选择发布/订阅或基于事件的系统。因此必须有发射器和处理程序。不过,这实际上只是重新包装了问题。如果ModuleA 可以发出事件并且ModuleB 可以监听事件,那么ModuleA 将不得不对ModuleB 有某种引用。这还不错,但现在我们必须考虑范围、复制 ctor、= 运算符等的所有时髦。我们别无选择,只能全力以赴。
例子
#include <iostream>
#include <string>
class Handler {
void HandleEvent();
};
class Emitter {
public:
// add handler to some kind of container
void AttachHandler(Handler *handler);
// loop through all handlers and call HandleEvent
void EmitEvent();
};
int main()
{
// scope A
Emitter emitter;
// scope B
{
Handler handler;
emitter.AttachHandler(handler);
}
// rats..
emitter.EmitEvent();
}
如果我们有一个名为MyObject 的东西包含一个我们想要监听的带有自己的EventEmitter 的组件(可能是一个套接字),事情会变得更糟。如果 MyObject 被复制,现在我们有这个内部 EventEmitter 和引用 MyObject 的处理程序可能不再存在!
所以也许我把它全部转储并切换到回调。但即便如此,某些对象仍然拥有 ptrs 或对可能不再存在的其他对象的引用!我们可以尽可能小心,但我们永远不知道会发生什么......
你知道,我想我需要说的是这个
- 任何对象都不应该有对另一个对象的引用或指针,除非它自己创建了那个对象。
现在必须通过管理这两个对象的更高级别的对象来将对象链接在一起......
...我应该坚持图形设计。
【问题讨论】:
-
评论不用于扩展讨论;这个对话是moved to chat。