[Qt开发思想探幽]QObject、模板继承和多继承

news2024/10/5 21:24:02

[Qt开发思想探幽]QObject、模板继承和多继承

    • [Qt开发探幽]QObject、模板继承和多继承
      • ***1. QObject为什么不允许模板继承:***
      • ***2.如果需要使用QObject进行多继承的话,子对象引用的父类链至多只能含有一个QObject***
      • ***3.如果使用模板类和QObject做多继承,编译不通过***
      • 问题场景

[Qt开发探幽]QObject、模板继承和多继承

当我们在用Qt开发一个软件框架的时候,在一个正式一点的库或者框架中,我们不可避免地想要使用继承,但是可能当我们开发完一个模块后,会发现一些问题,比如说在编译的时候发现父类会编译不通过。

先说结论:
1.Qt的QObject不支持模板继承。
2.如果需要使用QObject进行多继承的话,子对象引用的父类链至多只能含有一个QObject
3.如果使用模板类和QObject做多继承,依然会编译不通过

1. QObject为什么不允许模板继承:

  1. 元对象系统的复杂性:元对象系统(Meta-Object System)是 Qt 的一个重要特性,它允许在运行时获取对象的元信息,如类名、属性、信号、槽等。这个系统需要在编译阶段生成额外的元信息,并且在运行时维护一个元对象表。这个系统在处理模板类时会变得复杂,因为模板类的实例化和使用涉及到编译期和运行时的多个步骤,而元对象系统的设计主要针对静态类型的类层次结构。

  2. 编译期类型信息:元对象系统需要在编译期生成一些额外的类型信息,用于支持信号槽和反射等功能。模板类的实例化和类型信息在编译期可能变得模糊不清,这会导致元对象系统难以正确处理模板类的元信息。

  3. 类型擦除:C++ 模板的一个特点是类型擦除,即编译器在模板实例化时会生成不同的代码,但生成的代码是针对特定的类型的,而不是模板本身。这种类型擦除使得在运行时获取模板类型信息变得复杂,而元对象系统需要在运行时获取类型信息。

  4. 信号槽连接的动态性:信号槽机制允许在运行时动态地连接和断开信号槽。这就要求在运行时能够准确地识别信号和槽的参数类型,以便进行参数匹配。模板类的参数类型在编译期可能不确定,这给信号槽的动态连接带来挑战。

所以在继承了QObject的模板类中,编译会导致QMetaObject找不到元对象而发生编译期报错,所以请不要让任何模板类继承QObject。

你可能会问了,那类似QList和QSharedPointer类为什么可以是模板类,而且也是Qt的东西呢?这恰好是Qt这个库取巧的地方:所有的模板类都是容器,也就是说他们这个模板类中允许装入任何它们想要的东西。或者换句话说,Qt中所有的模板类,都不是QObject的子类,不然的话可以直接看头文件:QSharedPointer内部
也就是说,Qt内部其实自己也是遵循这个规则的:请不要让任何模板类继承QObject。

2.如果需要使用QObject进行多继承的话,子对象引用的父类链至多只能含有一个QObject

QObject有一个很重要的特点,就是不支持拷贝。

  1. 在 Qt 的多继承体系中,只有一个类可以拥有 QObject 功能,这个类必须是多继承链中的第一个类。QObject 类为了支持元对象系统、信号槽机制以及其他与运行时类型信息相关的功能,要求继承 QObject 的类在构造函数中通过传递 parent 参数来指定父对象。这个父对象就是用于建立对象之间关系的,例如在父对象析构时,它的子对象也会被析构。

  2. 由于 C++ 的多继承特性,当一个类需要继承多个类,而其中一个类是 QObject,为了保证 QObject 的正确功能,必须将 QObject 继承链放在多继承链的第一个位置。这是因为 QObject 继承链在构造和析构过程中有一些特殊的操作,需要在第一个类中执行。

3.如果使用模板类和QObject做多继承,编译不通过

这是因为 QObject 类需要在构造和析构过程中执行特殊的操作,以支持元对象系统、信号槽机制和其他与运行时类型信息相关的功能。而模板类的继承可能会干扰这些特殊操作,导致编译错误或者运行时问题。

QObject 的特殊操作需要在构造函数中执行,并且这些操作需要基于类的实际类型来进行。而模板类在编译时才会实例化,因此编译器在处理模板类时无法获得完整的类型信息,从而无法保证 QObject 的特殊操作能够正确地执行。

为了避免这些问题,Qt 推荐将 QObject 放在继承链的第一个位置,以确保 QObject 的特殊操作可以正确地执行。如果您的类需要多继承,可以考虑使用接口继承(纯虚函数)来实现所需的功能,以避免在多继承中使用 QObject 和模板类导致的问题。

问题场景

为什么我突然会想到这个问题呢,因为我确实遇到了,场景大概是这样的:
我现在在开发一个软件框架。我现在这个框架内的所有对象都需要包含一些信号和槽(这是为了统一上下信息的交换),我们管这个最底层的东西叫TSG_Caller,理论上我这个框架内所有的东西都应该要继承到这个TSG_Caller中,方便我进行管理:

在这里插入图片描述
它实际上只有一些信号和槽,我希望任何对象都能通过注册,在kernel内统一地操作这些信号与槽,不仅仅是一些细分的类,大类也要提供这些东西。

当我开发到一定程度之后,我细化到对某个设备的操控。于是我写了一个模板类,用来初始化一些模板类的基本类型。我希望不同的设备有不同的输入参数类型,于是我们就有了如下的设备模板类:

在这里插入图片描述
于是这里就出现问题了:QObject和模板类的继承兼容不能说不好,只能说基本完全不允许使用。当然了,这也是可以理解的,毕竟MetaObject这么强大的功能不能支持模板也是理所当然的事。

至于解决方法,那就只能改造这个设备类了,不能用模板类了,而是只能采用通用的输入类型。我这里因为输入的参数类型有限而且都是明文,所以我这里将所有的输入和输出都改成QString传输json字符串,当然了输入的字符串也要提供给外部一个判断的函数,以免外部输入错误。

修改后的接口如下:

在这里插入图片描述

不知道有没有更好的办法,也许有,但是目前我只想到这种比较简单的方法

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/940018.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

US-P2F-R-C双线圈插头式比例阀放大器

US-P2F-R-C型插头式安装比例放大器控制不带电反馈的单或双比例电磁铁的比例阀,如比例插装阀、比例方向阀、比例压力阀、比例流量阀、比例叠加阀等,带数显区显示及当前参数,如指令、电流、上下斜坡、颤振频率等,指令类型兼容0-10V、…

2023高教社杯数学建模思路 - 复盘:校园消费行为分析

文章目录 0 赛题思路1 赛题背景2 分析目标3 数据说明4 数据预处理5 数据分析5.1 食堂就餐行为分析5.2 学生消费行为分析 建模资料 0 赛题思路 (赛题出来以后第一时间在CSDN分享) https://blog.csdn.net/dc_sinor?typeblog 1 赛题背景 校园一卡通是集…

揭秘视频号创收计划:松松一个月赚1300+

我是卢松松,点点上面的头像,欢迎关注我哦! 这是卢松松一个月视频号的收益,1300元。自从视频号在五月份推出创作者分成计划以来,许许多多的视频号创作者开始获得了一些收益,这绝对是一项挺不错的进展。 目前…

Prometheus监控(一)

文章目录 监控对于企业和运维工作的重要性监控?告警?数据采集 Prometheus介绍Prometheus相对于老牌监控的优势和不足理想的监控系统的实现监控系统设计(架构师)监控系统的搭建数据采集的编写监控数据分析和算法稳定性测试监控自动…

无风扇迷你电脑信息与购买指南

本文将解释什么是无风扇迷你电脑,以及计算产品组合中你可以购买的一些不同的无风扇迷你电脑的信息指南。 无风扇迷你电脑是一种小型工业计算机,旨在处理复杂的工业工作负载。迷你电脑是通过散热器被动冷却可在各种类型的易失性环境中部署。无风扇微型计…

自动化运维:Ansible基础与命令行模块操作

目录 一、理论 1. Ansible 2.部署Ansible自动化运维工具 3.Ansible常用模块 4.hostsinverntory主机清单 二、实验 1.部署Ansible自动化运维工具 2.ansible 命令行模块 3.hostsinverntory主机清单 三、问题 1. ansible远程shell失败 2.组变量查看webservers内主机ip报…

开源在企业中的角色和价值

🌷🍁 博主猫头虎 带您 Go to New World.✨🍁 🦄 博客首页——猫头虎的博客🎐 🐳《面试题大全专栏》 文章图文并茂🦕生动形象🦖简单易学!欢迎大家来踩踩~🌺 &a…

Java集合大揭秘:优雅管理数据的智慧舞台

集合(Collections)是一种用于存储、组织和操作数据的重要工具。它们提供了各种数据结构和算法,帮助开发者高效地处理不同类型的数据。本文将带您深入了解Java集合框架,探索其核心概念、常用接口和类,以及在实际应用中的…

一个插件实现代码自由,快来试试吧

效果如下 开始操作 1.插件下载并解压 2.打开chrome浏览器,点击扩展程序–》管理扩展程序 3.打开开发者模式,加载已解压的扩展程序 4.加载AI工具 5.打开插件 6.回到主页,效果如下 7.点击ChatGPT 8.大概过30秒,邮箱注册 9.注册完成,可以…

智能气象站丨自动采集、自动存储、自动传输

智能气象站,能够同时自动采集周围环境中的空气湿度、空气温度、风速、风向、雨量、太阳辐射及大气压力、PM2.5、PM10等,多用户可以在手机或者电脑上同时查看实时数据。智能气象站与传统的气象站不同,采用了多种传感器技术对空气中的各项要素进…

谁说银行U盾有OK键,就不能远程连接调用?

如今很多公司都在用USB Server管理U盾,但是有的U盾不是要按OK键吗?怎么远程连接呢? 了解一下U盾OK键远程点按器! 有了它就可以配合USB Server自动点按OK键、远程连接调用网银U盾! 把U盾固定在点按器上, 将…

突破边界:文本检测算法的革新与应用前景

突破边界:文本检测算法的革新与应用前景 1.文本检测理论篇(文本检测方法介绍) 文本检测任务是找出图像或视频中的文字位置。不同于目标检测任务,目标检测不仅要解决定位问题,还要解决目标分类问题。 文本在图像中的…

大数据项目实战(Sqoop安装)

一,搭建大数据集群环境 1.4 Sqoop安装 1.sqoop安装 (1)上传安装包 (2)解压安装包 tar -zxvf sqoop-1.4.6.bin__hadoop-2.0.4-alpha.tar.gz -C /export/servers (3)重命名 mv sqoop-1.4.6.b…

新生军训报到须知情况发布

军训是每位高中生开学的第一课,它不仅能锻炼身体,培养毅力和团队合作精神,更能培养学生坚强的意志和自律的品质。作为班主任,应该与军训教官紧密合作,共同努力,为学生们提供一个有益的军训经验。 好消息&am…

AIGC:初学者使用“C知道”实现AI人脸识别

文章目录 前言人脸识别介绍准备工作创作过程生成人脸识别代码下载分类文件安装 OpenCV生成人脸识别代码(图片) 创作成果总结 前言 从前,我们依靠各种搜索引擎来获取内容,但随着各类数据在互联网世界的爆炸式增长,加上…

缓存技术实现

大家好 , 我是苏麟 , 今天聊一聊缓存 . 这里需要一些Redis基础 (可以看相关文章等) 本文章资料来自于 : 黑马程序员 如果想要了解更详细的资料去黑马官网查看 前言:什么是缓存? 缓存,就是数据交换的 缓冲区 (称作Cache [ kʃ ] ),俗称的缓存就是缓冲区内的数据,是存贮数据的…

SpringBoot异步方法支持注解@Async应用

SpringBoot异步方法支持注解Async应用 1.为什么需要异步方法? 合理使用异步方法可以有效的提高执行效率 同步执行(同在一个线程中): 异步执行(开启额外线程来执行): 2.SpringBoot中的异步方法支持 在SpringBoot中并不需要我们自己去创建维护线程或者线程池来异…

RTSP/Onvif协议安防视频平台EasyNVR录像模式自定义操作

TSINGSEE青犀视频安防监控平台EasyNVR可支持设备通过RTSP/Onvif流媒体协议接入,并能对接入的视频流进行处理与多端分发,包括RTSP、RTMP、HTTP-FLV、WS-FLV、HLS、WebRTC等多种格式。在智慧安防等视频监控场景中,EasyNVR可提供视频实时监控直播…

【通用消息通知服务】0x3 - 发送我们第一条消息(Websocket)

【通用消息通知服务】0x3 - 发送我们第一条消息 项目地址: A generic message notification system[Github] 实现接收/发送Websocket消息 Websocket Connection Pool import asyncio from asyncio.queues import Queue from asyncio.queues import QueueEmpty from contextli…

Triplet Fingerprinting(三元组网站指纹攻击)

文章信息 论文题目:《Triplet Fingerprinting: More Practical and Portable Website Fingerprinting with N-shot Learning》 期刊(会议):Proceedings of the 2019 ACM SIGSAC Conference on Computer and Communications Secur…