RAD Studio C++ 模板通用事件拦截器

问题描述

我一直在使用 RAD Studio XE 组件触发级联事件时遇到问题 - 例如当组件 A 的代码修改更改了组件 B 的内容,从而触发了组件 C 的更改等。 长话短说 - 通过 RAII 模式创建了一些阻塞机制。其中有多个,具体取决于我需要阻止的事件类型,例如 OnSelect 或 OnChange:

template<typename T,typename N>
class TOnChangeEventBlocker
{
public:
    TOnChangeEventBlocker(T* object)
        :m_pObject(object),m_pNotifyEvent(object->OnChange)
    {
        if (m_pObject)
        {
            m_pObject->OnChange = NULL;
        }
    }

    ~TOnChangeEventBlocker()
    {
        if (m_pObject)
        {
            m_pObject->OnChange = m_pNotifyEvent;
        }
    }
private:
    T* const    m_pObject;
    N           m_pNotifyEvent;
};

有没有办法让它更通用?让它与 __property 公开的私有事件处理程序一起工作?

与其编写过多的事件阻止程序,不如使用:一个、简单、通用的 TEventBlocker。

m_pObject->/*something here*/ = m_pNotifyEvent;

这是一个遗留代码和 RAD Studio XE 项目 - 没有太多的 c++11。


我跟随@Jarod42 成员指针的踪迹,面包屑引导我找到最终解决方案:

template <typename T>
    class TEventBlocker
    {
    public:
        TEventBlocker(T* f)
            : eventFunctionClassMember(f),eventFunction(NULL)
        {
            if (eventFunctionClassMember && *eventFunctionClassMember)
            {
                eventFunction               = *eventFunctionClassMember;
                *eventFunctionClassMember   = NULL;
            }
        }
        ~TEventBlocker()
        {
            if (eventFunctionClassMember)
            {
                *eventFunctionClassMember   = eventFunction;
            }
        }
    private:
        T*  eventFunctionClassMember;
        T   eventFunction;
    };

调用它(必须明确模板参数):

TEventBlocker<Classes::TNotifyEvent> blockSelect(&(SelectComponent->OnSelect));

解决方法

看来你只需要拿会员:

template <typename T>
class EventBlocker
{
public:
    EventBlocker(T& event)
        :m_event(event),m_old(event)
    {
        m_event = NULL; // nullptr; in C++11
    }

    ~EventBlocker()
    {
        m_event = m_old;
    }

private:
    EventBlocker(const EventBlocker&); // = delete; in C++11
    EventBlocker& operator=(const EventBlocker&); // = delete; in c++11

private:
    T& m_event;
    T m_old;
};

// C++17 CTAD would be enough,but before:
template <typename T>
EventBlocker<T> make_EventBlocker(T& event) { return {event}; }

然后:

auto eventBlocker = make_EventBlocker(myObject->OnChange);
// ...

相关问答

错误1:Request method ‘DELETE‘ not supported 错误还原:...
错误1:启动docker镜像时报错:Error response from daemon:...
错误1:private field ‘xxx‘ is never assigned 按Alt...
报错如下,通过源不能下载,最后警告pip需升级版本 Requirem...