刚入职,需要使用Qt开发。决定通过看Qt官方例程来学习Qt。水平有限,请指出。
第一步:先了解工程中的出现的宏定义
先了解一个宏
Q_UNUSED
这个宏没有实际意义,只是为了避免编译器的警告。
例如在程序中声明变量name没有使用它,在编译的时候编译器会发出没有使用的警告。但对于此类警告,对我们开发的意义不大,因此可以不需要管它。此时便可使用
Q_UNUSED(name);//编译器忽略了name没有使用的警告。
第二步:多工程中各个模块之间的关系
由于这个工程下有car和contrler两个类,先通过UML将两个类的逻辑关系进行分析。在仔细阅读代码之后,可以发现,car和contrler之间的关系是一种聚合的关系(一种整体合并的关系,与组合关系的区别是聚合中部分可以单独存在,而组合中部分不能单独存在),这样可以满足优先使用组合而不是用继承的习惯。
根据图中的对类的定义,可以画出该工程具体的类图如上图所示。
我们可以观察到,car和Controller是一种聚合关系,即是一种“has-a”。
第三步:多工程配置方法
在这个工程中,car和Controller是两个独立的模块,这符合使用Qt进行开发大型项目时,涉及到多个模块主要利用到的思想是模块化思想,目的是为了降低程序的复杂度,使程序设计、调试和维护等方便。
对于Qt中多工程而言。
如果需要管理多工程(pro),比如:库工程、界面工程,其中,每一个工程均可单独编译成功,但存在依赖关系。也就是说,lib2依赖于lib1,而UI依赖于lib2。
配置如下:
因此,在该工程中总的文件配置中添加:
TEMPLATE = subdirs //表示该工程为多工程
SUBDIRS = car \ //为该工程添加car工程模块
controller //为该工程添加controller工程模块
并且在car和controller各自模块中都有说明自身的来源:
安装+ =目标的来源
# install
target.path = $$[QT_INSTALL_EXAMPLES]/dbus/remotecontrolledcar/controller
INSTALLS += target
target.path = $$[QT_INSTALL_EXAMPLES]/dbus/remotecontrolledcar/car
INSTALLS += target
第四步:理解Qt Creator为我们做了些什么?
1:因为controller类是集成了QWdigets类,因此,Qt编译器会自动在debug或者relea目录下生成ui_controller.h的文件。
2:因为该工程为模块化编程,由多个独立模块组成的。此时编译器也会自动生成一些接口文件。例如,在本例中,由于controller中定义了car类,因此生成了car_interface类的接口文件,在此文件中,该接口类
OrgExampleExamplesCarInterfaceInterface在命名空间下:
namespace org {
namespace example {
namespace Examples {
typedef ::OrgExampleExamplesCarInterfaceInterface CarInterface;
}
}
}
因此,在controller类中对car初始化:
car = new org::example::Examples::CarInterface("org.example.CarExample", "/Car",
QDBusConnection::sessionBus(), this);
其中,该接口的构造函数原型为:
OrgExampleExamplesCarInterfaceInterface(const QString &service, const QString &path, const QDBusConnection &connection, QObject *parent = nullptr);
接下来我们就可以开始对源码的操作进行阅读和分析了。
第五步:源码阅读
请移步QtCreator中的实例。
第六步:疑问?
在工程中具体的各个独立的模块都有自己的main函数,但是一个exe文件即一个程序只有一个main函数入口,因此,在本例中,各个模块之间出现的两个main函数是如何进行通信的?
答:他们采用的进程通信。即每个模块对应一个进程。
但是为什么不直接将各个模块的类头文件进行包含,然后进行对象的创建。如果模块较多的话,开的进程也会增多,这样做的好处是什么。