一、簡介
由於博主本人是初學者對QT的機制不了解,所以遇到了一個比較大的坑,特此記錄一下。我遇到的問題是無法在靜態函數中向另外一個類發送信號。解決辦法:先將信號發送給同類中的普通函數,然后在從普通函數中發送信號給外部類。
二、C與C++中static的用法
這里不是介紹QT靜態函數信號的發送嗎,和static的用法有什么聯系,因為在編寫代碼中會出現靜態成員無法訪問普通成員的錯誤,這里我復制了菜鳥教程的圖片。
接下來先了解一下static的用法。
- C語言中static的作用
主要有三個作用:隱藏性、持久性、默認值為0
- 隱藏性:當我們同時編譯多個文件時,所有未加 static 前綴的全局變量和函數都具有全局可見性。
- 持久性:在函數內部使用static修飾變量時,不僅可以是變量具有隱藏性,還能增加變量生命。
- 默認初始化為 0:在靜態數據區,內存中所有的字節默認值都是 0x00,其實全局變量也具備這一屬性,因為全局變量也存儲在靜態數據區。
想了解具體的用法可以去菜鳥教程學習《C 語言中 static 的作用》。
- 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