当前位置: 首页 > news >正文

14.多态

用QT写一个无界面、新手友好的多态例子,并且详细讲解每一步的逻辑,彻底理解多态的核心含义和实际用法。

先通俗理解多态(新手版)

多态的核心是:同一个接口,不同的实现
就像你去餐厅点“饮料”(统一接口),服务员给你可乐/果汁/茶(不同实现)——你只需要说“要饮料”,不用关心具体是哪种,每种饮料都有自己的“喝法”(不同行为)。
在QT/C++中,多态主要通过虚函数实现:父类定义虚函数(统一接口),子类重写这个函数(不同实现),用父类指针/引用调用时,会自动执行子类的实现。

例子设计思路(无界面,贴近通信场景)

我设计一个极简但完整的多态例子,基于你熟悉的“通信”场景:

  1. 父类(通信设备基类):定义虚函数sendData()(统一接口)。
  2. 子类1(串口设备):重写sendData(),实现串口发送逻辑。
  3. 子类2(TCP设备):重写sendData(),实现TCP发送逻辑。
  4. 测试逻辑:用父类指针指向不同子类对象,调用同一个sendData(),观察不同的执行结果(多态的体现)。

完整代码实现(逐文件讲解)

1. 通信设备基类(commdevice.h)—— 定义统一接口

这是多态的“核心骨架”,用纯虚函数(=0)强制子类实现统一接口,保证所有通信设备都有sendData()方法。

#ifndef COMMDEVICE_H #define COMMDEVICE_H #include <QObject> #include <QString> #include <QDebug> // 通信设备基类(抽象类) class CommDevice : public QObject { Q_OBJECT public: // 构造函数(给父类传参) explicit CommDevice(QObject *parent = nullptr) : QObject(parent) {} // 虚析构函数:必须加!保证子类析构时能正确调用自己的析构 virtual ~CommDevice() { qDebug() << "CommDevice 基类析构"; } // 核心:虚函数(统一接口),子类必须重写 // virtual 关键字是多态的关键! virtual bool sendData(const QString &data) = 0; // 纯虚函数,无实现 }; #endif // COMMDEVICE_H
2. 串口设备子类(serialdevice.h/cpp)—— 重写接口

继承基类,实现串口特有的发送逻辑。

serialdevice.h
#ifndef SERIALDEVICE_H #define SERIALDEVICE_H #include "commdevice.h" // 串口设备子类:继承通信基类 class SerialDevice : public CommDevice { Q_OBJECT public: explicit SerialDevice(QObject *parent = nullptr) : CommDevice(parent) { qDebug() << "SerialDevice 串口设备创建"; } // 重写父类的虚函数(必须加 override 关键字,新手一定要加!防止写错) bool sendData(const QString &data) override; // 串口特有配置(子类扩展的功能) void setSerialPort(const QString &portName) { m_portName = portName; } private: QString m_portName; // 串口名(子类私有数据) }; #endif // SERIALDEVICE_H
serialdevice.cpp
#include "serialdevice.h" // 实现串口的sendData:这是串口特有的发送逻辑 bool SerialDevice::sendData(const QString &data) { qDebug() << "【串口发送】端口:" << m_portName << " 数据:" << data; // 这里可以加真实的QT串口发送代码,新手先简化 return true; // 模拟发送成功 }
3. TCP设备子类(tcpdevice.h/cpp)—— 重写接口

继承基类,实现TCP特有的发送逻辑。

tcpdevice.h
#ifndef TCPDEVICE_H #define TCPDEVICE_H #include "commdevice.h" // TCP设备子类:继承通信基类 class TcpDevice : public CommDevice { Q_OBJECT public: explicit TcpDevice(QObject *parent = nullptr) : CommDevice(parent) { qDebug() << "TcpDevice TCP设备创建"; } // 重写父类的虚函数 bool sendData(const QString &data) override; // TCP特有配置(子类扩展的功能) void setTcpAddr(const QString &ip, int port) { m_ip = ip; m_port = port; } private: QString m_ip; // TCP IP(子类私有数据) int m_port; // TCP 端口 }; #endif // TCPDEVICE_H
tcpdevice.cpp
#include "tcpdevice.h" // 实现TCP的sendData:这是TCP特有的发送逻辑 bool TcpDevice::sendData(const QString &data) { qDebug() << "【TCP发送】IP:Port:" << m_ip << ":" << m_port << " 数据:" << data; // 这里可以加真实的QT TCP发送代码,新手先简化 return true; // 模拟发送成功 }
4. 测试主函数(main.cpp)—— 核心:演示多态

这是最关键的部分,新手重点看这里的多态调用逻辑。

#include <QCoreApplication> #include "commdevice.h" #include "serialdevice.h" #include "tcpdevice.h" // 通用发送函数:接收父类指针,实现多态调用 // 新手重点:这个函数只认父类CommDevice,不知道传入的是串口还是TCP! void sendDataByDevice(CommDevice *device, const QString &data) { device->sendData(data); // 核心:调用父类接口,实际执行子类实现 } int main(int argc, char *argv[]) { QCoreApplication a(argc, argv); // -------------------------- // 步骤1:创建子类对象 // -------------------------- SerialDevice *serial = new SerialDevice; // 串口对象 serial->setSerialPort("COM3"); // 串口特有配置 TcpDevice *tcp = new TcpDevice; // TCP对象 tcp->setTcpAddr("192.168.1.100", 502); // TCP特有配置 // -------------------------- // 步骤2:多态核心操作 // -------------------------- // 父类指针指向串口子类对象 CommDevice *device1 = serial; device1->sendData("串口数据123"); // 实际执行SerialDevice::sendData // 父类指针指向TCP子类对象 CommDevice *device2 = tcp; device2->sendData("TCP数据456"); // 实际执行TcpDevice::sendData // -------------------------- // 步骤3:更实用的场景:通用函数 // -------------------------- // 同一个函数,传入不同子类对象,执行不同逻辑 sendDataByDevice(serial, "通用函数-串口发送789"); sendDataByDevice(tcp, "通用函数-TCP发送000"); // -------------------------- // 清理内存(新手别漏) // -------------------------- delete serial; delete tcp; return a.exec(); }

代码运行结果(新手重点看)

SerialDevice 串口设备创建 TcpDevice TCP设备创建 【串口发送】端口: COM3 数据: "串口数据123" 【TCP发送】IP:Port: "192.168.1.100" : 502 数据: "TCP数据456" 【串口发送】端口: COM3 数据: "通用函数-串口发送789" 【TCP发送】IP:Port: "192.168.1.100" : 502 数据: "通用函数-TCP发送000" CommDevice 基类析构 CommDevice 基类析构

逐行讲解多态核心逻辑(新手必看)

  1. 父类定义虚函数CommDevice中的virtual bool sendData(...) = 0;是“统一接口”,告诉所有子类:必须实现这个发送方法,但怎么实现我不管。
  2. 子类重写虚函数SerialDeviceTcpDevice都用override重写了sendData,分别实现串口/TCP的发送逻辑——这是“不同实现”。
  3. 父类指针指向子类对象
    • CommDevice *device1 = serial;:父类指针装了串口对象的地址。
    • device1->sendData(...):编译器不会直接调用父类的方法,而是“看指针实际指向的对象”——发现是串口对象,就执行串口的sendData
  1. 通用函数的妙用sendDataByDevice(CommDevice *device, ...)这个函数只接收父类指针,不管传入的是串口还是TCP,都能正确调用对应的发送方法——这就是多态的价值:写一次代码,适配多种场景

新手容易踩的坑(重点提醒)

  1. 忘记加 virtual 关键字:父类的函数如果不加virtual,就不会触发多态,调用的永远是父类的方法(但本例中父类是纯虚函数,会编译报错,反而更安全)。
  2. 重写函数时签名不一致:比如父类是sendData(const QString &),子类写成sendData(QString)——编译器会认为是新函数,不是重写!一定要加override关键字,编译器会帮你检查签名是否一致。
  3. 漏写虚析构:父类析构如果不加virtual,删除父类指针时,子类的析构不会执行,会导致内存泄漏。

总结

  1. 多态的核心:QT/C++中通过virtual虚函数实现,父类定义统一接口,子类重写实现不同逻辑,父类指针/引用调用时自动匹配子类实现。
  2. 关键语法:父类虚函数(virtual)+ 子类重写(override)+ 父类指针指向子类对象。
  3. 实际价值:写通用代码(比如sendDataByDevice)时,不用关心具体是哪种设备,新增UDP设备只需继承基类重写sendData,不用改原有代码(符合开闭原则)。

这个例子是新手能直接跑通的极简版本,没有复杂的QT底层通信逻辑,所有注意力都集中在多态的核心语法和逻辑上,你可以先复制代码跑起来,再逐行修改体会多态的效果。

http://www.jsqmd.com/news/357370/

相关文章:

  • 计算机小程序毕设实战-基于SpringBoot微信小程序的医院预约挂号系统设计与实现基于springboot+小程序的医院挂号系统设计与实现【完整源码+LW+部署说明+演示视频,全bao一条龙等】
  • 基于物联网的自动灌溉系统的设计与实现(有完整资料)
  • Python 列表推导式:一行代码搞定数据处理
  • 为什么 “Aa“ 和 “BB“ 的哈希值一样?聊聊 Java 里的“算法炸弹”
  • 计算机小程序毕设实战-基于springboot+小程序的社区资产管理app设计与实现基于springboot+vue实现的数据资产管理系统【完整源码+LW+部署说明+演示视频,全bao一条龙等】
  • Typora绘制-流程图
  • 定制别墅大门怎么选,解读熊熊集团企业文化及官网特色 - 工业设备
  • 说说河北从辰包装的包装盒生产设计,在唐山地区哪家口碑好? - 工业推荐榜
  • 《人月神话》阅读笔记1
  • 分析2026年螺旋输送机厂家选购要点及排名推荐 - 工业品网
  • 聊聊全铝家居工厂产品价格,多少钱能买到好用的? - myqiye
  • 2026年2月适合家庭出行的几款七座MPV车型参考 - 速递信息
  • Windows IP 配置工具 v1.3 丨绿色便携版
  • 适配性好的PVC排水管厂家推荐,浙江哪家比较靠谱? - 工业推荐榜
  • 深入解析 LRU 缓存:从 `@lru_cache` 到手动实现的完整指南
  • 2026年评价高的定位片,线卡,扎丝带厂家选型参考榜单 - 品牌鉴赏师
  • 2026年铝合金门窗厂家权威推荐榜:无缝焊接/极窄/定制化系统门窗,家居美学与长期性能的优选方案 - 速递信息
  • 2026年度高频焊管厂家推荐,专业服务与高品质产品全解析 - 工业品牌热点
  • 家庭七座MPV选购参考:多维度配置与车型排名 - 速递信息
  • 2026激光切管机十大品牌权威排名 十强品牌实力巡礼 - 匠言榜单
  • d10
  • 如何接口封装 注意事项 - 详解
  • 云原生模型训练十年演进
  • 技术深潜 | 世界模型工程化的三重困境:分布差异、精度速度权衡与误差累积
  • 2026年跨境电商公司权威推荐:郑州税务咨询/郑州财务外包/郑州跨境电商/郑州高企申请/郑州高企陪跑/选择指南 - 优质品牌商家
  • 2026年评价高的代理记账公司推荐:郑州财务外包、郑州跨境电商、郑州高企申请、郑州高企陪跑、郑州代理记账选择指南 - 优质品牌商家
  • 《三角洲行动》陪玩App全面对比:服务、价格、口碑,帮你快速决策 - 速递信息
  • 大语言模型应用十年演进
  • 2026年玻璃钢雕塑定制厂家权威推荐榜:户外大型/景观装饰/异形结构玻璃钢雕塑,耐久艺术与高精度成型优选方案 - 速递信息
  • 基于水文模型代码与建模技术的参数优化及预测模拟研究——从VIC模型到LSTM模型:粒子群与遗传...