2

我正在尝试为我的 GUI 窗口编写一个回调类。为了(希望)实现这一点,我正在使用代表。

typedef srutil::delegate2<void,DWORD,DWORD> CallbackMethod;
typedef std::map<MESSAGE_TYPE,std::vector<CallbackMethod>> CallbackMap;

MESSAGE_TYPE 是一个枚举。

我需要的是某种方式,当它被破坏时,通过某种持久/常量索引自动从映射中注销任何对象,而不依赖于修改类析构函数。

我的意思是,好吧,我的计划可能从一开始就有缺陷(我仍然在这些高级的东西中半盲编码),因为我指定回调以匹配某个签名,所以本质上任何使用此功能的类都必须有一些匹配它的方法,因此已经有点被迫遵守那些规则(耦合到类)。

所以我可能只是在其中引用地图。但是,仅此一项仍然需要遍历映射中的所有条目并删除与被销毁对象匹配的条目。

所以我想我需要的是某种自我意识的常量引用指针索引的东西。

这样的事情存在吗?在我看来,这应该是一个普遍的问题......

4

1 回答 1

2

在我的脑海中,我猜……不,它不存在(至少,对于 C++ 不存在)。

您的提议意味着一个复杂的情况(即使您没有使用回调)。你要求的东西,在它自己被破坏后,会负责从(可能)任何引用它的数据结构中删除对它自己的任何引用。这是一个相当高的要求,尤其不是 STL 的本意。


如果你真的想这样做(我相信你会这样做),那么这是我最初的想法。每次将您的对象添加到数据结构中时,您可能需要将数据结构注册到对象中,例如使用Object::Register(const std::vector<Object> &v). 然后,您可以将引用(实际上,您可能会捕获一个指针)存储到vector,因此您可以告诉它vector在销毁时删除对象。当然,这有两个问题:

  1. 它仍然非常复杂(特别是如果您想支持更多的结构而不仅仅是向量,如果您正在寻找一个完全通用的解决方案,则更是如此)。
  2. 它要求其他编码人员在将对象添加到结构的任何地方都遵循这种风格
  3. 它可能需要编辑 的析构函数Object,您明确告诉我们不应该这样做。

所以,是的,那里没有太多帮助。


就个人而言,我有一个更喜欢的解决方案,它围绕事件(特别是基于委托的事件,就像我们在 c# 中使用的那样)。如果您不熟悉这些工作原理,您可能想阅读本编程指南。再说一次,你可能不会,因为我们使用的是 c++,而不是 c#,而且我自己会描述它。

我喜欢事件想法的一个原因是您已经在使用回调。委托(如在 c# 中的委托)只是回调的扩展。vector<Callback>它们基本上将行为封装在一个Delegate类中。Delegate如果重载函数调用运算符,则该类允许通过一个操作调用所有这些方法。此外,就像delegate您已经在使用的一样,它可能是参数化类型。(事实上​​,当C++0x一切准备就绪时,这很快,可变参数模板也会很有帮助)。

无论如何,所有这一切的重点是您可以将 aDelegate作为任何类的成员变量:

class Object
{
    public:
    ... // whatever constructors, etc. you might need
    Delegate<void, Collection, EventArgs> destroyHandler;
    ... // and number of event handlers can be used.
};

现在,任何数据结构类都可以通过以下方式注册回调:

obj.destroyHandler += myDelegate;

wheremyDelegate是任何具有必要类型的函数。

但是,这种方法存在更多问题。具体来说,它需要一个全新的库,其中包含了解您的事件模型的数据结构。这不应该真的那么难,因为现有的 STL 容器可以简单地包装。这将是很多工作,每个人都必须决定使用你的新图书馆。

在该行中发现了另一个问题Delegate<void, Collection, EventArgs> destroyHandler;。这些类型参数中的每一个是什么意思?好吧,void应该很清楚:它只是方法的返回类型。而且,EventArgs很简单:它只是包装了需要传递给回调的任何数据。类型是最奇怪的Collection——我们为什么要参数化使用的类型集合?

这是为了规避在 c++ 中使用指向成员函数的指针的麻烦。虽然这样的指针是可能的,但它们使用起来很糟糕,而且(据我所知)没有办法从多种类型中获取指向成员函数的指针并将它们存储在一个集合中。

相反,我过去尝试过的(尽管我并没有真正完成这个想法)类似于

class MyVector
{

    static void DestructionHandler( MyVector & v, EventArgs & args )
    {
        // ... Handler code goes here
    }

};

需要注意的是参数MyVector & v:它替换了通常的this指针。另外,请注意该方法是static- 这允许它用作常规的旧 C 样式函数指针。

无论如何,我可能有点得意忘形,但是当你把所有这些放在一起时,你会得到一个相当不错的基于事件的系统,这在其他 OOP 语言中非常流行。此外,我告诉过你这是一项艰巨的任务!

于 2011-06-20T02:57:55.577 回答