Qt官方类程中DBus Controlled Car学习

 刚入职,需要使用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,指定需要添加的工程模块
  • 配置CONFIG为ordered指定顺序编译

因此,在该工程中总的文件配置中添加:

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函数是如何进行通信的?

答:他们采用的进程通信。即每个模块对应一个进程。

但是为什么不直接将各个模块的类头文件进行包含,然后进行对象的创建。如果模块较多的话,开的进程也会增多,这样做的好处是什么。

猜你喜欢

转载自blog.csdn.net/bao_120973681/article/details/81227253
car