0

我有一个回调类,在整个应用程序的某些地方使用。它是这样构造的:

struct A {
   void f();
}

A * callee = new A;
Callback_0 callback = CCallback_0(callee, &A::f);

callback现在可以存储和稍后调用。这样做的问题是,如果callee在回调创建和回调调用之间被破坏,程序就会崩溃(或更糟)。

到目前为止我能想到的唯一解决方案:任何想要成为被调用者的类都必须从基Callee类继承:

class Callee {
public:
   void registerCallback(const Callback& c) {
      _callbacks.push_back(c);
   }
   ~Callee() {
      std::for_each(_callbacks.begin(), _callbacks.end(), [](Callback& c){c.disable();});
   }

private:
   std::vector<Callback> _callbacks;
}

这种设计的缺点是我必须继承每个可能需要调用的类。有没有更好的办法?我更喜欢 C++03 解决方案,我只有有限的 C++11 支持(受 MSVC2010 和 Mac 上的 clang 限制)。

4

2 回答 2

1

如果我们认为您面临的一般问题是,您正在对两个独立对象的创建和删除活动进行排序,并且在这些状态之间(C & D),您希望它们之间有关联。

这对于类设计不是很具体,callback对于任何此类问题领域都是非常通用的。callback类设计只是整个问题集的一个子类 - 在我们的系统设计中以不同的命名法重新出现。

AFAI,只有两种方法可以处理此类设计问题-a
。将创建/销毁的所有权授予调用者对象。您可以通过将被调用者的属性传递给回调并将被调用者的生命周期的责任交给调用者来实现这一点。这可以确保 - 在操作过程中对象不会被意外删除 - 例如callback在当前设计中。

湾。另一种方法是使用shared_ptror object countermechasim (如评论中所述),这将确保只有在use-up被调用者的最后一个实例之后才被释放。

当然,这些都是技术上的方法,现在要考虑它如何适合我们的设计并对其有意义。从这个角度来看,Option b似乎比Option a.

也就是说,根据我的经验,我没有看到太多a or b使用这两个选项的代码。我们只是让calleeandcaller独立,并确保它callee不会被仔细的编码破坏:)

于 2013-09-10T09:42:27.833 回答
0

第一个解决方案是通过类本身管理所有调用者。这可以通过从您已经描述的某种管理器类派生来完成。

第二个是设置一些拥有所有可调用实例和调用者列表的管理器类。实例必须由这个管理器类创建和删除,所有注册的回调必须由这个管理器实例拥有。

下一个可能是某种 smart/auto_ptr 解决方案。每个指针都连接到某种取消注册回调的管理器类。

基本上,您必须知道实例何时死亡,而您想如何执行此操作并不重要。

对我来说,这听起来像是一个基本的设计问题。外部世界必须知道任何类的某些(可能是未知的)实例的存在,并且没有明确定义的接口来在不同的类及其实例之间进行交互。也许代理可以帮助管理界面。但是,如果不了解您的程序的其余部分,我们将找不到最佳解决方案。

于 2013-09-10T09:42:18.960 回答