资讯动态

Qt 类完整例程【逐词拆解 + 逐步骤执行保姆教程】

发布时间:2026/10/13 9:08:58 来源:尧图企业网站定制
前面学了纯 C 普通类现在学习 Qt 的类。 记住一句话Qt 类本质就是 C 的类只是 Qt 框架扩展了一套【QObject 对象模型】本例选用 Qt 最基础的自定义 QObject 子类只用到信号槽不涉及 UI 界面Qt 控制台项目更容易理解// myphone.h 头文件 #ifndef MYPHONE_H #define MYPHONE_H // 引入QObject头文件QObject是Qt所有对象的根类 #include QObject // 类定义开始 class MyPhone : public QObject { // Q_OBJECT宏Qt独有开启元对象系统支持信号槽 Q_OBJECT public: // 构造函数 explicit MyPhone(QObject *parent nullptr); // 普通成员函数发射打电话信号 void startCall(QString number); // 信号Qt独有只声明不用写函数实现 signals: void callSignal(QString num); // 槽函数接收信号执行业务逻辑 public: void onCallReceive(QString num); }; // 类定义结束 #endif // MYPHONE_H// myphone.cpp #include myphone.h #include QDebug // 构造函数实现 MyPhone::MyPhone(QObject *parent) : QObject(parent) { } void MyPhone::startCall(QString number) { // emit发射信号Qt关键字 emit callSignal(number); } void MyPhone::onCallReceive(QString num) { qDebug() 收到来电号码 num; }// main.cpp #include QCoreApplication #include myphone.h int main(int argc, char *argv[]) { QCoreApplication a(argc, argv); MyPhone phone1; MyPhone phone2; // connect 信号槽连接函数 connect(phone1, MyPhone::callSignal, phone2, MyPhone::onCallReceive); phone1.startCall(10086); return a.exec(); }运行输出收到来电号码10086第一部分头文件class MyPhone : public QObject逐词拆解class MyPhone : public QObjectclassC 关键字含义定义一个类作用告诉编译器下面要定义一张 “图纸”。和上一节普通 C 类的 class 完全一样。必须写没有 class编译器不会识别这是类。MyPhone类名我们自定义的名字代表这个 Qt 类叫 MyPhone我的手机驼峰命名首字母大写只是图纸名称此时没有创建对象不存储数据不占对象内存: public QObject:冒号代表继承C 原生语法public公有继承QObjectQt 提供的基类父类图纸整句含义MyPhone 类继承自 QObject自动拥有 QObject 自带全部能力信号槽、对象树、元对象系统普通 C 类没有这一段继承 QObject 是 Qt 类的标志性写法{ }大括号大括号内部存放这个类的全部内容宏、成员函数、信号。};结尾分号不能丢。Q_OBJECTQ_OBJECTQ_OBJECT是 Qt 提供的宏不是标准 C 关键字作用开启 Qt 元对象系统只有写了这个当前类才能使用信号、槽。强制规则必须写在继承 QObject 的类内部写在头文件里面添加或者删除 Q_OBJECT 之后必须执行 qmake重新构建项目否则编译报错虚表错误。普通 C 类没有 Q_OBJECT。explicit MyPhone(QObject *parent nullptr);构造函数explicit MyPhone(QObject *parent nullptr);explicitC 关键字禁止隐式类型转换。Qt 继承 QObject 的类构造函数基本都会加 explicit。MyPhone构造函数名字和类名完全相同没有返回值创建对象自动调用。QObject *parent形参父对象指针。parent 用来设置 Qt 对象树父对象销毁时自动删除子对象自动管理内存。 nullptr默认参数。创建对象时如果不传 parentparent 默认等于空指针。nullptr空指针代表没有父对象。void startCall(QString number);void返回值类型函数执行完不返回任何数据startCall成员函数名字(QString number)参数列表调用函数时需要传入一个 QString 字符串存到局部变量 number 中。;声明结束头文件只做声明函数体写在 cpp 文件signals:Qt 的标记不是 C 原生关键字含义下面定义的全部是信号信号特点只写函数声明不需要写 {} 函数体moc 工具自动帮我们生成实现代码。void callSignal(QString num);callSignal信号函数可以携带参数用来向外传递数据。public:和普通 C 一样public 下面的函数外部代码main可以调用。void onCallReceive(QString num);槽函数用来接收信号收到信号后执行里面代码函数体在 cpp 实现。#ifndef / #define / #endif头文件保护宏防止头文件被多次重复包含导致编译报错Qt 头文件默认都带。#ifndef MYPHONE_H #define MYPHONE_H // 代码 #endif // MYPHONE_H第二部分 cpp 文件逐词讲解MyPhone::MyPhone(QObject *parent) : QObject(parent) { }MyPhone::MyPhone::作用域解析符。读作 “的”含义MyPhone 类里面的 MyPhone 构造函数: QObject(parent)初始化列表子类构造函数执行前先调用父类 QObject 的构造函数把 parent 传给父类Qt 继承 QObject 的类构造函数必须写这个。emit callSignal(number);emitQt 宏标记 “发射信号”callSignal(number)触发 callSignal 信号把 number 的值传递出去emit 本质是空宏编译后消失只是给程序员看的标记。void MyPhone::onCallReceive(QString num) { qDebug() 收到来电号码 num; }MyPhone::onCallReceiveMyPhone 类里面的 onCallReceive 函数qDebug()Qt 打印输出工具替代 cout可以直接打印 QString 类型输出运算符可以拼接多个内容自动换行。第三部分 main.cpp 逐词拆解重点看phone1.startCall(10086);和 connectMyPhone phone1; MyPhone phone2;MyPhoneQt 类名图纸phone1对象名按照 MyPhone 图纸创建出来的实例。 phone1 和 phone2 是两个独立对象各自拥有自己的成员。 创建的时候自动调用 MyPhone 构造函数parent 默认是 nullptr。connect(phone1, MyPhone::callSignal, phone2, MyPhone::onCallReceive);connect是 Qt 全局函数用来把信号和槽绑定在一起。 参数逐个拆解phone1 取地址代表信号发送对象是 phone1指针MyPhone::callSignal取信号函数地址phone1 发出的信号 callSignalphone2接收信号的对象 phone2MyPhone::onCallReceive接收信号后执行的槽函数一句话把 phone1 的 callSignal 信号连接到 phone2 的 onCallReceive 槽函数。只要 phone1 发射 callSignalphone2 的 onCallReceive 就自动执行。phone1.startCall(10086);phone1对象名字我们操作 phone1 这个实例.点号成员访问运算符读作 “的”。访问 phone1 对象里面的成员函数startCall成员函数名称**()圆括号**代表调用、执行这个函数。括号里面10086 作为参数传给 number;语句结束标记。整句含义调用 phone1 对象的 startCall 成员函数传入号码 10086。 startCall 内部执行emit callSignal(number)→ 发射信号。 因为 connect 提前绑定好了phone2 的 onCallReceive 自动被调用打印信息。return a.exec();a是 QCoreApplication 对象a.exec()开启 Qt事件循环监听信号事件。普通 C 控制台程序不需要事件循环Qt 信号槽程序必须开启事件循环。第四部分 完整执行流程一步一步跟着走QCoreApplication a(argc, argv);创建 Qt 应用程序对象Qt 程序必须要有这个管理事件循环。MyPhone phone1;创建 phone1 对象自动调用 MyPhone 构造函数parentnullptr。MyPhone phone2;创建 phone2 对象自动调用构造函数parentnullptr。connect(...)建立连接phone1 的 callSignal 信号绑定 phone2 的 onCallReceive 槽。此时函数不会执行只是登记绑定关系。phone1.startCall(10086);调用 phone1 的 startCall 函数传入参数 10086 执行emit callSignal(number)→ 发射 callSignal 信号附带参数 10086 Qt 事件系统查找所有绑定这个信号的槽函数 找到 phone2.onCallReceive自动执行把 10086 传给形参 num qDebug 打印收到来电号码10086return a.exec();开启事件循环等待后续信号事件。本例没有更多事件程序等待最后退出。第五部分 Qt 类 vs 普通 C 类对比复习巩固项目普通 C 类MobilePhone 例子Qt 继承 QObject 的类MyPhoneclass 关键字有定义类有定义类底层仍然 C继承可选一般继承 QObjectQ_OBJECT无需要写开启元对象系统signals、emit不存在Qt 扩展实现信号槽通信内存管理new 对象必须手动 delete设置 parent父对象自动释放子对象对象拷贝支持❌禁止拷贝QObject 不能直接赋值复制事件循环不需要信号槽程序需要 a.exec () 事件循环新手高频踩坑加了 Q_OBJECT忘记执行 qmake报 undefined reference to vtable 虚表错误。信号槽参数槽的参数不能比信号参数多否则连接失败。QObject 子类不能写MyPhone p phone1;拷贝对象编译报错。connect 里要传对象地址所以要写phone1不要漏掉 。头文件末尾};分号不能丢。

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价 →
↑