• Qt 静态函数发送信号


    一、简介

      由于博主本人是初学者对QT的机制不了解,所以遇到了一个比较大的坑,特此记录一下。我遇到的问题是无法在静态函数中向另外一个类发送信号。解决办法:先将信号发送给同类中的普通函数,然后在从普通函数中发送信号给外部类。

    二、C与C++中static的用法

      这里不是介绍QT静态函数信号的发送吗,和static的用法有什么联系,因为在编写代码中会出现静态成员无法访问普通成员的错误,这里我复制了菜鸟教程的图片。

    接下来先了解一下static的用法。

    1. C语言中static的作用
      主要有三个作用:隐藏性、持久性、默认值为0
    • 隐藏性:当我们同时编译多个文件时,所有未加 static 前缀的全局变量和函数都具有全局可见性。
    • 持久性:在函数内部使用static修饰变量时,不仅可以是变量具有隐藏性,还能增加变量生命。
    • 默认初始化为 0:在静态数据区,内存中所有的字节默认值都是 0x00,其实全局变量也具备这一属性,因为全局变量也存储在静态数据区。
      想了解具体的用法可以去菜鸟教程学习《C 语言中 static 的作用》。
    1. C++ 中static的作用
      C++中使用static需要主要的地方
    • 静态成员函数中不能调用非静态成员。
    • 非静态成员函数中可以调用静态成员。因为静态成员属于类本身,在类的对象产生之前就已经存在了,所以在非静态成员函数中是可以调用静态成员的。
    • 静态成员变量使用前必须先初始化(如 int MyClass::m_nNumber = 0;),否则会在 linker 时出错。

    修饰成员变量

    • 静态数据成员可以实现多个对象之间的数据共享,它是类的所有对象的共享成员,它在内存中只占一份空间,如果改变它的值,则各对象中这个数据成员的值都被改变。
    • 静态数据成员是在程序开始运行时被分配空间,到程序结束之后才释放,只要类中指定了静态数据成员,即使不定义对象,也会为静态数据成员分配空间。
    • 静态数据成员可以被初始化,但是只能在类体外进行初始化,若未对静态数据成员赋初值,则编译器会自动为其初始化为 0。
    • 静态数据成员既可以通过对象名引用,也可以通过类名引用。

    修饰成员函数

    • 静态成员函数和静态数据成员一样,他们都属于类的静态成员,而不是对象成员。
    • 非静态成员函数有 this 指针,而静态成员函数没有 this 指针。
    • 静态成员函数主要用来方位静态数据成员而不能访问非静态成员。
      想了解具体的用法可以去菜鸟教程学习《C/C++ 中 static 的用法全局变量与局部变量》。

    三、程序源码

    ClassA.h 文件

     1 #ifndef CLASSA_H
     2 #define CLASSA_H
     3 
     4 #include <QObject>
     5 #include <iostream>
     6 
     7 class ClassA : public QObject
     8 {
     9     Q_OBJECT
    10 public:
    11     ClassA();
    12     ~ClassA();
    13 
    14     static void SignalGeneration();     //静态函数,信号将从此函数发生
    15 
    16 private:
    17     static ClassA *myClassA;     //它在内存中只占一份空间
    18 
    19 signals:
    20     void SigExternal(QString str);      //向外部的类发送信号
    21     void SigInsideDelier(char *str);      //发送信号到此类的信号槽
    22 
    23 private slots:
    24     void SlotInsideDelier(char *str);     //内部槽 用于响应内部信号
    25 };
    26 
    27 #endif // CLASSA_H

    ClassA.cpp文件

     1 #include "ClassA.h"
     2 
     3 ClassA *ClassA::myClassA = NULL;    // 静态成员变量使用前必须先初始化,否则使用是会提示变量未定义
     4 
     5 ClassA::ClassA()
     6 {
     7     myClassA = this;
     8     connect(this, &ClassA::SigInsideDelier, [this](char *str)
     9         {
    10             emit SlotInsideDelier(str);
    11         });
    12 }
    13 
    14 void ClassA::SignalGeneration()
    15 {
    16     const char *str = "信号生产成功";
    17     emit myClassA->SigInsideDelier((char *)str);
    18 }
    19 
    20 void ClassA::SlotInsideDelier(char *str)
    21 {
    22     emit SigExternal(QString(str));
    23 }
    24 
    25 ClassA::~ClassA()
    26 {
    27 
    28 }

    widget.h文件

     1 #ifndef WIDGET_H
     2 #define WIDGET_H
     3 
     4 #include <QWidget>
     5 #include "ClassA.h"
     6 
     7 QT_BEGIN_NAMESPACE
     8 namespace Ui { class Widget; }
     9 QT_END_NAMESPACE
    10 
    11 class Widget : public QWidget
    12 {
    13     Q_OBJECT
    14 
    15 public:
    16     Widget(QWidget *parent = nullptr);
    17     ~Widget();
    18 
    19 private slots:
    20     void on_pushButton_clicked();
    21 
    22     void classA_msg(QString str);
    23 
    24 private:
    25     Ui::Widget *ui;
    26 };
    27 #endif // WIDGET_H

    widget.cpp文件

     1 #include "widget.h"
     2 #include "ui_widget.h"
     3 #include <iostream>
     4 #include "ClassA.h"
     5 
     6 using namespace std;
     7 
     8 ClassA *classA;
     9 
    10 Widget::Widget(QWidget *parent)
    11     : QWidget(parent)
    12     , ui(new Ui::Widget)
    13 {
    14     classA = new ClassA();
    15 
    16     connect(classA, SIGNAL(SigExternal(QString)), this, SLOT(classA_msg(QString)));    //注意这里传递信号必须使用QString不能使用char *,否则接收数据会异常,具体原因未知
    17     ui->setupUi(this);
    18 }
    19 
    20 Widget::~Widget()
    21 {
    22     delete classA;
    23     delete ui;
    24 }
    25 
    26 void Widget::on_pushButton_clicked()
    27 {
    28     ClassA::SignalGeneration();
    29 }
    30 
    31 void Widget::classA_msg(QString str)
    32 {
    33     ui->plainTextEdit->appendPlainText(str);
    34 }

    程序界面

    四、运行测试

  • 相关阅读:
    C#前端画表
    JavaScript中遍历获取Json中属性值
    【数据库】Redis(5)--Redis发布订阅
    【java框架】SpringBoot(9) -- Springboot中如何优雅的进行字段校验
    【开发工具】-- IDEA集成Git在实际项目中的运用
    【Java代码之美】 -- Java必会的工具库,减少代码量的利器
    【java框架】SpringMVC(4) -- JSON相关的数据返回
    聊聊基于jdk实现的spi如何与spring整合实现依赖注入
    聊聊springcloud项目同时存在多个注册中心客户端采坑记
    feign请求返回值反序列LocalDateTime异常记录
  • 原文地址:https://www.cnblogs.com/ybqjymy/p/16613300.html
Copyright © 2020-2023  润新知