news 2026/4/20 1:55:59

14.多态

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
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底层通信逻辑,所有注意力都集中在多态的核心语法和逻辑上,你可以先复制代码跑起来,再逐行修改体会多态的效果。

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

互联网大厂Java面试实战:核心语言、微服务与AI技术全解析

互联网大厂Java面试实战&#xff1a;核心语言、微服务与AI技术全解析 面试背景 本次面试场景设定在一家互联网大厂&#xff0c;求职者谢飞机应聘Java后端开发岗位。面试官严肃专业&#xff0c;谢飞机则以幽默风趣的风格面对问题。面试涵盖Java核心技术、微服务架构、大数据处理…

作者头像 李华
网站建设 2026/4/17 12:35:57

springboot毕业设计在线寻亲网任务书 开题报告

目录毕业设计任务书&#xff1a;在线寻亲网&#xff08;SpringBoot实现&#xff09;开题报告结构建议项目技术支持可定制开发之功能亮点源码获取详细视频演示 &#xff1a;文章底部获取博主联系方式&#xff01;同行可合作毕业设计任务书&#xff1a;在线寻亲网&#xff08;Spr…

作者头像 李华
网站建设 2026/4/19 13:52:46

人工智能应用- 语言处理:02.机器翻译:规则方法

语言的多样性为人类交流带来了巨大的障碍。因此&#xff0c;自计算机诞生之初&#xff0c;科学家们便开始设想利用机器来实现跨语言的沟通。1947 年&#xff0c;美国数学家沃伦韦弗&#xff08;Warren Weaver&#xff09;首次提出了机器翻译的设想&#xff0c;并在 1949 年发表…

作者头像 李华
网站建设 2026/4/18 4:25:12

人工智能应用- 语言处理:04.统计机器翻译

20 世纪 80 年代末&#xff0c;研究者开始探索基于数据驱动的统计机器翻译&#xff08;Statistical Machine Translation, SMT&#xff09;方法。1990 年&#xff0c;IBM Watson 的研究者在《Computational Linguistics》上发表了题为《A Statistical Approach to Ma- chine Tr…

作者头像 李华
网站建设 2026/4/18 10:05:20

模型加速十年演进

模型加速&#xff08;Model Acceleration&#xff09; 的十年&#xff08;2015–2025&#xff09;&#xff0c;是从“算力暴力输出”向“效率极致压榨”&#xff0c;再到“系统级原生对齐”的深刻演进。 这十年中&#xff0c;模型加速完成了从单一算子优化到端到端全链路加速&a…

作者头像 李华
网站建设 2026/4/18 7:41:55

HoRain云--CentOS7中国IP访问限制实战指南

&#x1f3ac; HoRain 云小助手&#xff1a;个人主页 ⛺️生活的理想&#xff0c;就是为了理想的生活! ⛳️ 推荐 前些天发现了一个超棒的服务器购买网站&#xff0c;性价比超高&#xff0c;大内存超划算&#xff01;忍不住分享一下给大家。点击跳转到网站。 目录 ⛳️ 推荐 …

作者头像 李华