news 2026/9/30 2:34:10

Qt 新手必学核心语法(基于 C++,逐句讲解,保姆级)

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Qt 新手必学核心语法(基于 C++,逐句讲解,保姆级)

前置记住:Qt 是C++ 框架,下面这些是 Qt 额外增加的宏 / 关键字,不是标准 C++,靠 moc(元对象编译器)处理。普通 C++ 语法(if、for、class、指针、vector 等)照常使用。 环境:Qt Creator + Qt Widgets 项目

一、Q_OBJECT【最重要!90% 新手报错根源】

写法

#include <QObject> class MyClass : public QObject // 必须继承QObject或者它的子类(QWidget/QMainWindow等) { Q_OBJECT // 这一行! public: explicit MyClass(QObject *parent = nullptr); };

详细解释

  1. 作用:开启 Qt【元对象系统】。有了它,才能使用信号槽、反射、Q_PROPERTY。
  2. 强制规则(新手必背)
    • Q_OBJECT必须写在头文件 (.h)的类里面;
    • 这个类必须继承 QObject(窗口类 QMainWindow、QWidget 都是 QObject 子类);
    • 类名后面大括号内第一行附近写;
  3. ⚠️ 踩坑:加了 Q_OBJECT 之后,一定要 qmake/CMake 重新构建,不然会报undefined reference to vtable虚表错误。

简单一句话:要用信号槽,就必须写 Q_OBJECT;不用信号槽,可以不写。


二、signals:信号

写法

signals: void sendData(int num); // 信号函数声明

详细解释

  1. 信号:类对外发出的通知,代表 “发生了某个事件”。 例:按钮点击clicked()就是 QPushButton 自带的信号。
  2. 特点:
    • 只写声明,不用写函数实现(不需要写 {} 函数体),moc 自动生成代码;
    • 信号可以带参数,用来传递数据;
    • 信号函数返回值一般是void;
  3. 触发信号用emit。

理解类比:信号 = 报警器,出事了就响,只负责通知,不做处理。

三、slots:槽函数(旧写法,了解即可)

Qt5 之后推荐用普通成员函数当槽,slots:属于老式语法

public slots: void onRecvData(int num);
  1. 槽函数:用来接收信号、执行具体业务逻辑的函数。
  2. 特点:必须自己写函数实现(.cpp 里写函数体);参数数量、类型最好和发送的信号匹配。

类比:槽 = 接到报警器通知后,执行的动作(关门、报警提示)

✅ Qt5 新写法推荐:不用写slots:,普通 public 函数就可以作为槽,直接 connect 连接。

四、emit发射信号

emit sendData(100);

解释

  • emit是一个空宏(编译后直接消失,只是给人看标记),作用:触发信号。
  • 当代码执行emit xxx(),就会把这个信号发送出去,所有连接到这个信号的槽函数会被调用。
  • 只能在信号所在的类的成员函数内部emit。

一句话:emit = 按下报警器开关。

信号槽完整最小示例(h 文件)

#ifndef MYCLASS_H #define MYCLASS_H #include <QObject> class MyClass : public QObject { Q_OBJECT public: explicit MyClass(QObject *parent = nullptr); void testEmit(); // 普通函数,用来发射信号 signals: void sendMsg(QString str); // 信号,不带实现 public: void recvMsg(QString str); // Qt5新方式:普通函数直接做槽 }; #endif // MYCLASS_H

cpp 文件:

#include "myclass.h" #include <QDebug> MyClass::MyClass(QObject *parent) : QObject(parent) { } void MyClass::testEmit() { emit sendMsg("Hello Qt"); // 发射信号 } void MyClass::recvMsg(QString str) { qDebug() << "收到消息:" << str; }

五、connect()信号槽连接函数【最常用】

Qt5 新式写法(推荐,新手优先学这个!类型安全)

connect(objA, &MyClass::sendMsg, objB, &MyClass::recvMsg);

参数拆解:

connect(发送者对象, &类名::信号名, 接收者对象, &类名::槽函数)

  1. objA:信号是谁发出来的对象
  2. &MyClass::sendMsg:取信号函数的地址
  3. objB:谁接收信号
  4. &MyClass::recvMsg:接收后执行的函数地址

旧版 Qt4 字符串写法(不推荐,容易写错,类型不检查)

// Qt4老写法,尽量不要用 connect(objA, SIGNAL(sendMsg(QString)), objB, SLOT(recvMsg(QString)));

connect 第五个可选参数(连接方式,了解)

connect(a, &A::sig, b, &B::slot, Qt::QueuedConnection);
  • Qt::AutoConnection默认:自动判断同线程 / 跨线程
  • Qt::DirectConnection:同步,发射信号立刻执行槽(同线程)
  • Qt::QueuedConnection:异步,放进接收者事件队列(跨线程必须用这个)

六、explicit构造函数(类构造函数前面)

explicit MyClass(QObject *parent = nullptr);
  1. 作用:禁止隐式类型转换。Qt 所有继承 QObject 的类构造,基本都会加 explicit。
  2. 新手记住:写继承 QObject 的类,构造函数前面加上explicit就对了。
  3. parent = nullptr:父对象,Qt 内存管理核心。

七、parent 父对象机制(Qt 内存管理,非常重要)

// new一个对象,指定父对象为this QPushButton *btn = new QPushButton("按钮", this);
  • 普通 C++:new 出来的对象,必须手动 delete,否则内存泄漏
  • Qt QObject 子类:指定 parent 父对象,父对象销毁时,自动 delete 所有子对象,不用手动 delete!
  • this代表当前类实例。

注意:只对继承 QObject 的类生效,普通 C++ 类没用。

八、QDebug打印输出,代替 cout

#include <QDebug> qDebug() << "数字:" << 123 << "字符串" << QString("测试");
  • qDebug()Qt 自带打印,专门输出 Qt 类型(QString、QVariant)
  • 可以连续<<拼接,不需要 endl,自动换行
  • 发布版本可以关掉 qDebug 输出。

九、QStringQt 字符串(高频使用)

标准 C++ 是std::string;Qt 界面用QString

QString str = "hello"; // 互转 std::string s = str.toStdString(); QString str2 = QString::fromStdString(s);

常用方法:

str.isEmpty(); // 判断是否空 str.size(); // 字符长度 str.arg(100); // 字符串占位替换,超级常用 QString info = QString("当前数值:%1").arg(99); // info结果:"当前数值:99"

十、this关键字(和 C++ 一样,Qt 大量使用)

this指向当前实例对象。 常见场景:

  1. 构造函数初始化列表
  2. connect 里传递当前对象作为发送 / 接收者
  3. new 控件时,设置 parent = this

十一、初始化列表(C++ 语法,但 Qt 构造函数天天用)

MyClass::MyClass(QObject *parent) : QObject(parent) // 初始化列表,调用父类构造函数 { }
  • : QObject(parent):子类构造时,先调用父类 QObject 的构造,把 parent 传给父对象。

所有继承 QObject 的类,构造函数都要写这个。

二、新手高频踩坑汇总

  1. 加了Q_OBJECT后,忘记qmake 重新构建,报虚表 undefined reference。解决:【构建】->【qmake】再重新构建项目
  2. 信号参数多于槽函数参数:可以;槽参数多于信号参数:不行!
  3. QObject 的子类不能拷贝、不能赋值,不能写MyClass a = b;,QObject 禁用拷贝构造。
  4. 界面控件(QPushButton、QLabel)操作必须在主线程,子线程不能直接操作 UI 控件。

三、最简完整可运行 Demo(控制台 Qt 项目)

myclass.h

#ifndef MYCLASS_H #define MYCLASS_H #include <QObject> class MyClass : public QObject { Q_OBJECT public: explicit MyClass(QObject *parent = nullptr); void test(); signals: void sendText(QString txt); public: void slotRecv(QString txt); }; #endif // MYCLASS_H

myclass.cpp

#include "myclass.h" #include <QDebug> MyClass::MyClass(QObject *parent) : QObject(parent) { } void MyClass::test() { emit sendText("Qt信号槽测试"); } void MyClass::slotRecv(QString txt) { qDebug() << "收到信号内容:" << txt; }

main.cpp

#include <QCoreApplication> #include "myclass.h" int main(int argc, char *argv[]) { QCoreApplication a(argc, argv); MyClass obj1; MyClass obj2; // 连接信号槽 connect(&obj1, &MyClass::sendText, &obj2, &MyClass::slotRecv); obj1.test(); // 调用函数,发射信号 return a.exec(); }

运行输出:收到信号内容:"Qt信号槽测试"

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/30 2:32:42

GoogLeNet 含并行连结的网络(Inception)详解:从原理到多框架动手实现

人工智能深度学习机器学习教程 【免费下载链接】d2l-zh 《动手学深度学习》&#xff1a;面向中文读者、能运行、可讨论。中英文版被70多个国家的500多所大学用于教学。 项目地址&#xff1a; https://gitcode.com/GitHub_Trending/d2/d2l-zh 点击查看 免费下载 《动手学深度学…

作者头像 李华
网站建设 2026/9/30 2:32:05

软文推广采购避坑指南:从行业价值到头部服务商选型全攻略

在品牌营销精细化、流量成本持续攀升的当下&#xff0c;传统硬性广告投放存在成本高、时效短、留存弱、信任度低等短板&#xff0c;已经难以满足企业长效品牌建设需求。而软文推广凭借公信力强、内容留存久、搜索引擎收录稳定、适配AI信息采信逻辑、可沉淀品牌数字资产等核心优…

作者头像 李华
网站建设 2026/9/30 2:31:45

海外储能升压一体机:箱变保护如何适配环网柜狭小空间

摘 要&#xff1a;储能升压一体机行业处于高速扩容阶段&#xff0c;集成化、液冷大功率机型成为主流&#xff0c;一体化方案凭借成本、施工、运维优势逐步替代传统分体设备。储能升压一体机高低侧多为环网柜&#xff0c;空间小&#xff0c;且变压器容量大&#xff0c;因此需要把…

作者头像 李华
网站建设 2026/9/30 2:31:27

Linux下shell执行多用户命令

一、前言 国庆期间&#xff0c;个人服务器断电了&#xff0c;导致服务器上面数据库等应用全部关闭了&#xff0c;但是启动应用时候需要切换到对应的用户&#xff0c;让同事启动&#xff0c;又存在各种应用比较麻烦&#xff0c;个人应用也没有提前编写维护手册&#xff0c;导致服…

作者头像 李华