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 Attention is all you need 的代码运行
  • ¥15 一个服务器已经有一个系统了如果用usb再装一个系统,原来的系统会被覆盖掉吗
  • ¥15 使用esm_msa1_t12_100M_UR50S蛋白质语言模型进行零样本预测时,终端显示出了sequence handled的进度条,但是并不出结果就自动终止回到命令提示行了是怎么回事:
  • ¥15 前置放大电路与功率放大电路相连放大倍数出现问题
  • ¥30 关于<main>标签页面跳转的问题
  • ¥80 部署运行web自动化项目
  • ¥15 腾讯云如何建立同一个项目中物模型之间的联系
  • ¥30 VMware 云桌面水印如何添加
  • ¥15 用ns3仿真出5G核心网网元
  • ¥15 matlab答疑 关于海上风电的爬坡事件检测