在 C++ 中订阅按钮以动态触发某些功能?

发布于 2024-08-16 00:20:54 字数 206 浏览 7 评论 0原文

我正在尝试创建一个按钮类(抽象),以便我可以设置在程序加载时动态单击时该按钮将触发什么功能。

我想通过读取 XML 文件来构造所有按钮,这是为了避免代码复制,因此只有 1 个“通用”按钮类对我来说非常有用。

我想知道您是否可以动态传递有关方法的必要信息,例如指向方法所有者和问题名称中的方法的指针,或者甚至更好的是指向方法的直接指针,以便单击按钮时调用该函数/方法?

I'm trying to make a button class (abstract) so I can set what function is that button going to trigger when clicked dynamically when my program load.

I want to construct all my buttons by reading XML files, this is to avoid code replication so having only 1 "generic" button class is really useful for me.

I was wondering if you could dynamically pass the necessary information about a method, like a pointer to the method's owner and method in question name, or even better the direct pointer to the method, for a button to call that function/method when clicked ?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

画尸师 2024-08-23 00:20:54

由于指向函数的指针是运行时工件,因此您无法将其存储在离线配置中。我看到两种可能适合您所描述的解决方案:

  1. 将您的函数放入动态库中并按名称加载它们 - 这样您的配置会将按钮映射到库路径/函数名称对,
  2. 在启动时构建命名函数指针的“注册表”,可能是一些哈希表,因此配置会将按钮映射到哈希键。

但根据经验,我会说构建此类设施通常是矫枉过正,并且配置很快就会变得比应用程序本身更重。

一些额外的指导:Boost.Signals、QT Signals、命令和责任链设计模式。

Since pointer to function is a runtime artifact you cannot store that in the offline configuration. I see two solutions that might fit what you describe:

  1. put your functions into a dynamic library and load them by name - that way your configuration would map a button to library path/function name pair,
  2. build a "registry" of named function pointers at startup, probably some hash table, so the configuration would map a button to the hash key.

From experience though I would say that building such facilities are usually overkill, and the configuration quickly becomes heavier then the app itself.

Some additional pointers: Boost.Signals, QT Signals, Command and Chain of Responsibility design patterns.

挽心 2024-08-23 00:20:54

您可以在通用 Button 类中创建一个 SetFunctor 方法,该方法接受函数对象作为参数。然后,您创建一个 Call 方法来调用包装在函数对象内的函数。像这样的事情:

    template<typename FUNC>
    class Functor
    {
        typedef FUNC (*FC)();
        FC func;
    public:
        Functor( FC f ) : func(f) {}
        ~Functor() {}
        FUNC Call() { return func(); }
        FUNC operator()() const { return Call(); }
    };

    class Button
    {
        std::auto_ptr<Functor<void> > pfunc;
    public:
        Button() {}
        ~Button() {}
        void SetFunctor( void(*fc)() )
        {
            pfunc.reset( new Functor<void>( fc ) ); // now owns ptr;
        }

        void Call()
        {
            pfunc->Call();
        }
    };

    ...
    void changeColor()
    {
      // do work
    }

    Button obj;
    obj.SetFunctor( changeColor );
    obj.Call();

当然,我可以使用更好的智能指针和/或更好的技术,但这应该让您了解我所暗示的要点。另请注意,此 Functor 对象只能接受没有参数的函数。您可以根据自己的喜好更改此设置。我希望它有帮助!

更新:添加了一些修复。对此感到抱歉!

You can create a SetFunctor method in your generic Button class, which accepts a function object as a parameter. Then you create a Call method that calls the function wrapped inside the function object. Something like this:

    template<typename FUNC>
    class Functor
    {
        typedef FUNC (*FC)();
        FC func;
    public:
        Functor( FC f ) : func(f) {}
        ~Functor() {}
        FUNC Call() { return func(); }
        FUNC operator()() const { return Call(); }
    };

    class Button
    {
        std::auto_ptr<Functor<void> > pfunc;
    public:
        Button() {}
        ~Button() {}
        void SetFunctor( void(*fc)() )
        {
            pfunc.reset( new Functor<void>( fc ) ); // now owns ptr;
        }

        void Call()
        {
            pfunc->Call();
        }
    };

    ...
    void changeColor()
    {
      // do work
    }

    Button obj;
    obj.SetFunctor( changeColor );
    obj.Call();

Of course I could've used better smart pointers and or better techniques, but this should give you a gist of what I was hinting at. Also note, that this Functor object can only accept functions that have no parameters. You can change this to your liking. I hope it helps!

UPDATE: A few fixes added. Sorry about that!

被你宠の有点坏 2024-08-23 00:20:54

您正在寻找信号/槽模式。

在 C++ 中,两个流行的选项是 升压信号 和 < a href="http://libsigc.sourceforge.net/" rel="nofollow noreferrer">sigc。

You are looking for the signal/slot pattern.

In C++ two popular options are boost signals and sigc.

自由范儿 2024-08-23 00:20:54

有几种方法可以将按钮链接到 C++ 中的函数 - 您可以使用函数指针(这有点可怕),或者使用信号和槽模式,该模式提供函数指针的功能并具有更高的类型安全性。

至于在运行时根据配置文件连接函数指针或信号和槽,要优雅地完成此操作将需要反射,而 C++ 并没有为您提供反射。我怀疑这将是丑陋的部分。

There are a couple of ways to link a button to a function in C++ - you can use function pointers (which are somewhat scary), or a signals and slots pattern which provides the functionality of function pointer with more type safety.

As far as wiring up the function pointers or signals and slots at run time based on a config file, to do this elegantly will require reflection, which C++ doesn't provide for you. I suspect this will be the ugly part.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文