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

在Qt中,直接include <moc_xxxxx.cpp> 为什么不会出现符号冲突的错误?

在逛Qt官方社区的时候看到这样一个帖子:
https://forum.qt.io/topic/117973/how-does-include-moc_-cpp-work
大概的意思是moc_xxx.cpp如果已经被编译器编译,那么在另一个cpp文件中include同一个moc_xxx.cpp应该出现符号冲突才对,但是Qt却能正确运行。对于这个问题,@KH-219Design的回答是:

qmake 负责处理这个场景的编译问题。它会扫描cpp代码和 *.pro 文件以生成 Makefile。如果在编译器和链接器遵循在Makefile中包含的 “Automatic MOC”时,当在源代码中没有找到 #include “moc_myclass.cpp” 时,会修改makefile以包含moc_myclass.cpp:
*.o 文件:

> SOURCES       = ../src/main.cpp \
>                 ../src/myclass.cpp moc_myclass.cpp 
>                 OBJECTS       = main.o \
>                 myclass.o \
>                 **moc_myclass.o** 

当#include 了 moc 文件时,qmake 会扫描到,并相应地调整 Makefile,移除moc_myclass.cpp:

> SOURCES       = ../src/main.cpp \
>                 ../src/myclass.cpp OBJECTS       = main.o \
>                 myclass.o

可见qmake非常智能。

笔者使用cmake的工程对qmake的这个特性进行验证,发现其设计也更为巧妙。

首先,在使用了Q_OBJECT类的源码中,增加一行:
在这里插入图片描述
在CMake的Qt项目中,qmake会将一个工程的所有moc_xxx.cpp放在同一个文件中包含,例如:
XXX_autogen\mocs_compilation_Release.cpp,这个文件内容如下:
在这里插入图片描述

这样的好处是在新增Q_OBJECT类的时候,不需要修改cmakelist或者改变构建工具的行为。

接下来,我们对比//#include <moc_xxCardObjBase.cpp>注释前和注释后的区别。发现如果在源码直接包含moc_xxCardObjBase.cpp时,mocs_compilation_Release.cpp文件内容确实少了 include <2FELSIXJDY/moc_xxCardObjBase.cpp>。所以qmake确实会扫描源文件中,include<moc_xxx.cpp>的行为!!
在这里插入图片描述

这个过程中,注意到XXX_autogen\include_Debug下新生成了moc_XXCardObjBase.cpp,这个文件和之前生成的moc_XXCardObjBase.cpp.d目录不一样,之前生成的在2FELSIXJDY子目录下。
在这里插入图片描述
出于好奇也对比了这两个文件的内容,对比了moc_XXCardObjBase.cpp与2FELSIXJDY/moc_XXCardObjBase.cpp两个文件,发现其内容几乎一模一样,只有头文件的include路径变了。因为这个头文件采用的是相对路径,如果不变,会导致编译不过。
在这里插入图片描述
所以,假如我们自作聪明,直接在cpp里写#include <2FELSIXJDY/moc_XXCardObjBase.cpp>,那么反而会遇到路径错误,试了一下,果然如此。

更进一步

想要进一步了解Qt MOC的技术细节,请移步:《探究Qt5【元对象编译器,moc】的 原理和技术细节》

相关文章:

  • UTONMOS:探索未来区块链与元宇宙的游戏奇妙融合
  • linux的常用系统维护命令
  • Linux的一些杂项函数总结
  • rabbitmq消息队列提出的问题(个人想法)
  • 有哪些好的 Stable Diffusion 提示词(Prompt)可以参考?
  • hive零基础入门
  • QT5:在窗口右上角显示图标
  • 天猫商品列表数据接口(Tmall.item_search)
  • VSCode中常用的快捷键
  • Opencv学习项目6——pyzbar
  • Linux 静态库和动态库
  • 思考如何学习一门编程语言?
  • 实习总结 --- 内部平台使用
  • 【聊聊原子性,中断,以及nodejs中的具体示例】
  • 通过MATLAB控制TI毫米波雷达的工作状态
  • JS 中的深拷贝与浅拷贝
  • Angular 响应式表单之下拉框
  • ComponentOne 2017 V2版本正式发布
  • DataBase in Android
  • Git初体验
  • input的行数自动增减
  • iOS筛选菜单、分段选择器、导航栏、悬浮窗、转场动画、启动视频等源码
  • Javascript 原型链
  • JavaScript服务器推送技术之 WebSocket
  • JS进阶 - JS 、JS-Web-API与DOM、BOM
  • Laravel 实践之路: 数据库迁移与数据填充
  • MaxCompute访问TableStore(OTS) 数据
  • Netty+SpringBoot+FastDFS+Html5实现聊天App(六)
  • passportjs 源码分析
  • React-生命周期杂记
  • Redash本地开发环境搭建
  • vue从入门到进阶:计算属性computed与侦听器watch(三)
  • Web Storage相关
  • 不用申请服务号就可以开发微信支付/支付宝/QQ钱包支付!附:直接可用的代码+demo...
  • 二维平面内的碰撞检测【一】
  • 给Prometheus造假数据的方法
  • ------- 计算机网络基础
  • 那些年我们用过的显示性能指标
  • 如何进阶一名有竞争力的程序员?
  • 如何设计一个微型分布式架构?
  • 如何优雅的使用vue+Dcloud(Hbuild)开发混合app
  • 算法---两个栈实现一个队列
  • 学习笔记TF060:图像语音结合,看图说话
  • 一个普通的 5 年iOS开发者的自我总结,以及5年开发经历和感想!
  • 【运维趟坑回忆录 开篇】初入初创, 一脸懵
  • ​软考-高级-信息系统项目管理师教程 第四版【第19章-配置与变更管理-思维导图】​
  • #[Composer学习笔记]Part1:安装composer并通过composer创建一个项目
  • #NOIP 2014# day.1 T3 飞扬的小鸟 bird
  • #我与虚拟机的故事#连载20:周志明虚拟机第 3 版:到底值不值得买?
  • $(document).ready(function(){}), $().ready(function(){})和$(function(){})三者区别
  • (6)设计一个TimeMap
  • (ISPRS,2023)深度语义-视觉对齐用于zero-shot遥感图像场景分类
  • (博弈 sg入门)kiki's game -- hdu -- 2147
  • (二刷)代码随想录第16天|104.二叉树的最大深度 559.n叉树的最大深度● 111.二叉树的最小深度● 222.完全二叉树的节点个数
  • (规划)24届春招和25届暑假实习路线准备规划