Register__ 2022-09-15 22:23 采纳率: 89.5%
浏览 73
已结题

Qt 的 信号与槽机制怎么实现的?

Qt 中函数与槽机制是怎么实现的(机制) 网上大都是文字讲解,有点看不懂。我不知道我现在这个需求和 qt 的信号与槽机制是不是一个想法。

假如现在有这个这样的情景,有一个链接函数 connect(int , Func ) , 把一个 int 类型 和一个 函数 绑在一起,有一个

 Caller(intarg1,arg2,arg3,...) 

函数 ,可以调用 传入的 int 对应绑定的func ,这里 func的返回类型,参数都不一样。

1 . 我的思路 是 用 unorderedMap<int, 函数 类型 (这里我就不知道 怎么写了, 因为函数的签名都不一样,如果都是 特定的 比如 void()(void) 那就可以直接存了> 我是想每个int 绑定的函数 不一定都是 void()(void) ;

2 . Caller 实现 就 直接

return Map [x] (这里写参数 );

可是c++ 没有 像 java C# 那种装不同类型的 容器,我就想到了 Qt 那个 connect(发出者,信号函数,接收者,槽函数) ; 这个怎么实现的 ?**

我本来是想设计一个 类似于菜单的 类, 里面有item 就好似 菜单的每一个条例, 我把每一个item 都 给一个索引,把对应的索引和 每个 item 对应要做的事情 绑定在一起。

鄙人平常想法比较多,大学 学校 teacher 基本不讲这些东西(哎!),我可能缺少一些其他知识 比如 设计模式,进程/线程通信,网络(基本没学过,还是大二)啥的,不知道和这个有没有关系,感觉如何设计对象,把事情抽象 好难,每次看到一些C++ 库中那些 各种对象的继承方式,构造方式,就很想学,但是不知道怎么开始, 直接看人家代码 就和天书一样。

  • 写回答

4条回答 默认 最新

  • _GX_ 2022-09-16 00:22
    关注

    一般实现方法是丢弃函数签名,把绑定的函数存在一个容器内,然后再实现operator()用来传递参数。下面是一个例子供你参考,下面代码编译器支持C++17。

    #include <functional>
    #include <map>
    #include <any>
    #include <iostream>
    
    template <typename ReturnType>
    class Callable
    {
    public:
        Callable() {}
    
        template <typename Func>
        Callable(Func &&func) : Callable(std::function(std::forward<Func>(func))) {}
    
        template <typename... Args>
        Callable(std::function<ReturnType(Args...)> func) : _any(func) {}
    
        template <typename... Args>
        ReturnType operator()(Args &&...args)
        {
            return std::invoke(std::any_cast<std::function<ReturnType(Args...)>>(_any), std::forward<Args>(args)...);
        }
    
    private:
        std::any _any;
    };
    
    class Test
    {
    public:
        template <typename Func>
        void connect(int signal, Func &&func)
        {
            _map[signal] = func;
        }
    
        template <typename... Args>
        void call(int signal, Args... args)
        {
            _map[signal](std::forward<Args>(args)...);
        }
    
    private:
        std::map<int, Callable<void>> _map;
    };
    
    void f1(int x, int y)
    {
        std::cout << "f1(): x=" << x << ", y=" << y << std::endl;
    }
    
    void f2(std::string str, int x, int y)
    {
        std::cout << "f2(): str=" << str << ", x=" << x << ", y=" << y << std::endl;
    }
    
    int main()
    {
        Test t;
        t.connect(1, f1);
        t.connect(2, f2);
        t.call(1, 1, 2);
        t.call(2, std::string("hello"), 3, 4);
        return 0;
    }
    
    $ g++ -Wall -std=c++17 main.cpp
    $ ./a.out
    f1(): x=1, y=2
    f2(): str=hello, x=3, y=4
    
    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论
查看更多回答(3条)

报告相同问题?

问题事件

  • 系统已结题 9月26日
  • 已采纳回答 9月18日
  • 赞助了问题酬金10元 9月15日
  • 创建了问题 9月15日

悬赏问题

  • ¥15 C#算法问题, 不知道怎么处理这个数据的转换
  • ¥15 YoloV5 第三方库的版本对照问题
  • ¥15 请完成下列相关问题!
  • ¥15 drone 推送镜像时候 purge: true 推送完毕后没有删除对应的镜像,手动拷贝到服务器执行结果正确在样才能让指令自动执行成功删除对应镜像,如何解决?
  • ¥15 求daily translation(DT)偏差订正方法的代码
  • ¥15 js调用html页面需要隐藏某个按钮
  • ¥15 ads仿真结果在圆图上是怎么读数的
  • ¥20 Cotex M3的调试和程序执行方式是什么样的?
  • ¥20 java项目连接sqlserver时报ssl相关错误
  • ¥15 一道python难题3