一、简介

由于博主本人是初学者对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 文件

#ifndef CLASSA_H
#define CLASSA_H #include <QObject>
#include <iostream> class ClassA : public QObject
{
Q_OBJECT
public:
ClassA();
~ClassA(); static void SignalGeneration(); //静态函数,信号将从此函数发生 private:
static ClassA *myClassA; //它在内存中只占一份空间 signals:
void SigExternal(QString str); //向外部的类发送信号
void SigInsideDelier(char *str); //发送信号到此类的信号槽 private slots:
void SlotInsideDelier(char *str); //内部槽 用于响应内部信号
}; #endif // CLASSA_H

ClassA.cpp文件

#include "ClassA.h"

ClassA *ClassA::myClassA = NULL;    // 静态成员变量使用前必须先初始化,否则使用是会提示变量未定义

ClassA::ClassA()
{
myClassA = this;
connect(this, &ClassA::SigInsideDelier, [this](char *str)
{
emit SlotInsideDelier(str);
});
} void ClassA::SignalGeneration()
{
const char *str = "信号生产成功";
emit myClassA->SigInsideDelier((char *)str);
} void ClassA::SlotInsideDelier(char *str)
{
emit SigExternal(QString(str));
} ClassA::~ClassA()
{ }

widget.h文件

#ifndef WIDGET_H
#define WIDGET_H #include <QWidget>
#include "ClassA.h" QT_BEGIN_NAMESPACE
namespace Ui { class Widget; }
QT_END_NAMESPACE class Widget : public QWidget
{
Q_OBJECT public:
Widget(QWidget *parent = nullptr);
~Widget(); private slots:
void on_pushButton_clicked(); void classA_msg(QString str); private:
Ui::Widget *ui;
};
#endif // WIDGET_H

widget.cpp文件

#include "widget.h"
#include "ui_widget.h"
#include <iostream>
#include "ClassA.h" using namespace std; ClassA *classA; Widget::Widget(QWidget *parent)
: QWidget(parent)
, ui(new Ui::Widget)
{
classA = new ClassA(); connect(classA, SIGNAL(SigExternal(QString)), this, SLOT(classA_msg(QString))); //注意这里传递信号必须使用QString不能使用char *,否则接收数据会异常,具体原因未知
ui->setupUi(this);
} Widget::~Widget()
{
delete classA;
delete ui;
} void Widget::on_pushButton_clicked()
{
ClassA::SignalGeneration();
} void Widget::classA_msg(QString str)
{
ui->plainTextEdit->appendPlainText(str);
}

程序界面

四、运行测试

参考文献

C 语言中 static 的作用:https://www.runoob.com/w3cnote/c-static-effect.html

C/C++ 中 static 的用法全局变量与局部变量:https://www.runoob.com/w3cnote/cpp-static-usage.html

Qt知识点梳理 —— 静态函数发送信号:https://blog.csdn.net/tingzhiyi/article/details/112631489

QT之静态函数发送信号的更多相关文章

  1. Qt 使用 lambda 表达式做为槽函数时为什么使用 QObject::sender() 获取到的发送信号对象指针为空?

    /*! Returns a pointer to the object that sent the signal, if called in a slot activated by a signal; ...

  2. QT槽函数获取信号发送对象

    Qt 在槽函数中获取信号发送对象 Qt中提供了一个函数 qobject_cast(QObject *object),可以通过这个函数判断信号发出对象 Qt 帮助文档的解释: Returns the g ...

  3. 第七章 探秘Qt的核心机制-信号与槽

    第七章 探秘Qt的核心机制-信号与槽 注:要想使用Qt的核心机制信号与槽,就必须在类的私有数据区声明Q_OBJECT宏,然后会有moc编译器负责读取这个宏进行代码转化,从而使Qt这个特有的机制得到使用 ...

  4. 在Qt中将函数发送到主线程执行

    考虑这样一种需求,使用Qt的线程类QThread在后台执行操作(比如说拷贝文件)的时候发生了错误,产生了一个错误信息需要提醒给用户,在后台输出很显然是不够的,因为用户可能根据就没有任何控制台可供程序输 ...

  5. QThread 与 QObject的关系(QObject可以用于多线程,可以发送信号调用存在于其他线程的slot函数,但GUI类不可重入)

    QThread 继承 QObject..它可以发送started和finished信号,也提供了一些slot函数. QObject.可以用于多线程,可以发送信号调用存在于其他线程的slot函数,也可以 ...

  6. 2.QT-窗口组件(QWidget),QT坐标系统,初探消息处理(信号与槽)

    本章主要内容如下: 1) 窗口组件(QWidget) 2) QT坐标系统 3) 消息处理(信号与槽) 窗口组件(QWidget) 介绍 Qt以组件对象的方式构建图形用户界面 Qt中没有父组件的顶级组件 ...

  7. Qt对象模型之一:信号和槽

    一.信号和槽机制概述 信号槽是 Qt 框架引以为豪的机制之一.所谓信号槽,实际就是观察者模式.当某个事件发生之后,比如,按钮检测到自己被点击了一下,它就会发出一个信号(signal).这种发出是没有目 ...

  8. Linux 发送信号

    使用kill命令 --在命令行执行kill命令.向指定进程发送信号. 使用kill函数 int kill(pid_t pid,int sig); --参数pid指定一个要杀死的进程,而sig是要发送的 ...

  9. Linux 命令 - kill: 向进程发送信号

    kill 命令通常用来 “杀死”(终止)进程,它可以用来终止运行不正常的程序或者反过来拒绝终止的程序.kill 命令准确地说并不是 “杀死” 进程,而是给进程发送信号(signal). 和文件一样,进 ...

随机推荐

  1. 【UGUI源码分析】Unity遮罩之Mask详细解读

    遮罩,顾名思义是一种可以掩盖其它元素的控件.常用于修改其它元素的外观,或限制元素的形状.比如ScrollView或者圆头像效果都有用到遮罩功能.本系列文章希望通过阅读UGUI源码的方式,来探究遮罩的实 ...

  2. 95后新同事年薪35W+,老员工却“自愿申请”降薪10%,中年职场人正在崩溃

    蔡依林在演唱会上说过的一句话:"在乐坛摸爬滚打这么多年,遭遇了那么多质疑和嘲讽还能挺立到今天,然后想说40岁是个很棒的年纪......",让很多在职场打拼多年的老员工感慨颇深. 真 ...

  3. 身边好几个技术一般的程序员都面上了,阿里P7门槛降低?

    经常在网上的论坛里看到讨论程序员的级别,尤其在跳槽类的信息里可以看到对标阿里P7,百度T6,腾讯3.1等字眼,似乎大厂的级别俨然可以成为业内的通用货币,类似于高考分数一样,哪一档就对应着什么样的待遇. ...

  4. CentOS的crond系统定时服务

    crond 服务管理 [root@node01 ~]# service crond start           (启动服务) [root@node01 ~]# service crond stop ...

  5. Dll文件的创建与测试C#

    创建Dll文件 首先使用VS 2019创建Dll项目,创建项目时选择"类库",如下图 在项目中创建类文件,添加测试代码: namespace PlantSim_C_Interfac ...

  6. pikachu CSRF

    CSRF简介 CSRF 是 Cross Site Request Forgery 的 简称,中文名为跨域请求伪造在CSRF的攻击场景中,攻击者会伪造一个请求(一般是一个链接)然后欺骗目标用户进行点击, ...

  7. IDEA spring boot项目插件打包方式jar

    一.打包 1.pom.xml中添加插件依赖 <build> <plugins> <plugin> <!--打包成可执行jar--> <groupI ...

  8. Windows内核-7-(IRP)I/O请求包

    Windows内核-7-(IRP)I/O请求包 IRP(I/O Request Packet)就是一个进行I/O操作的请求包. IRP是一个结构体,谁分配谁就得释放,通常由执行体里的管理器,获取内核驱 ...

  9. NOIP 模拟 $19\; \rm w$

    题解 \(by\;zj\varphi\) 树形 \(dp\) 题目 有一个结论:对于一个图,有多少奇度数的点,处以二就是答案,奇度数指的是和它相连的边中被反转的是奇数 证明很好证 那么设 \(dp_{ ...

  10. C#基础知识---装箱与拆箱

    一.定义 装箱:将值类型转化为引用类型,装箱一般会在堆上分配一块内存,用于存储要转换的值. 拆箱:将引用类型转化为值类型 注:.NET 2.0 引入的泛型其实在很大的程度上解决了装拆箱产生的类型转换问 ...