linux下qt加载boost,信号槽的实现实例—— Qt 和 Boost

Qt 的信号槽和 Boost.Signals 由于有着截然不同的设计目标,因此二者的实现、强度也十分不同。将二者混合在一起使用也不是不可能的,我们将在本系统的最后一部分来讨论这个问题。

使用信号槽

信号槽是伟大的工具,但是如何能更好的使用它们?相比于直接函数调用,有三点值得我们的注意。一个信号槽的调用:或许会比直接函数调用耗费更多的时间/空间;

可能不能使用 inline;

对于代码阅读者来说可能并不友好。

使用信号槽进行解耦,我们获得的最大的好处是,连接两端的对象不需要知道对方的任何信息。Button 同动作的连接是一个很典型的案例。例如如下信息:class Elevator

{

public:

enum Direction { DownDirection=-1, NoDirection=0, UpDirection=1 };

enum State { IdleState, LoadingState, MovingState };

// ...

// signals:

void floorChanged(int newFloor );

void stateChanged( State newState );

void directionChanged( Direction newDirection );

};

Elevator 类,也就是电梯,不需要知道有多少显示器正在监听它的信号,也不需要知道这些显示器的任何信息。每一层可能有一个屏幕和一组灯,用于显示电梯的当前位置和方向,另外一些远程操控的面板也会显示出同样的信息。电梯并不关心这些东西。当它穿过(或者停在)某一层的时候,它会发出一个 floorChanged(int) 信号。或许,交通信号灯是更合适的一个例子。

你也可以实现一个应用程序,其中每一个函数调用都是通过信号来触发的。这在技术上说是完全没有问题的,然而却是不大可行的,因为信号槽的使用无疑会丧失一部分代码可读性和系统性能。如何在这其中做出平衡,也是你需要考虑的很重要的一点。

Qt 方式

了解 Qt 信号槽最好的莫过于 Qt 的文档。不过,这里我们从一个小例子来了解信号槽的 Qt 方式的使用。// Qt Signals and Slots

class Button :public QObject

{

Q_OBJECT

Q_SIGNALS:

void clicked();

};

class Page :public QObject

{

Q_OBJECT

public Q_SLOTS:

void reload();

};

// given pointers to an actual Button and Page:

connect(button,SIGNAL(clicked()), page, SLOT(reload()));

Boost.Signals 方式

了解 Boost.Signals 的最好方式同样是 Boost 的文档。这里,我们还是先从代码的角度了解一下它的使用。// Boost.Signals

class Button

{

public:

boost::signal clicked;

};

class Page

{

public:

void reload();

};

// given pointers to an actual Button and Page:

button->clicked.connect( boost::bind(&Page::reload, page));

对比

或许你已经注意到上面的例子中,无论是 Qt 的实现方式还是 Boost 的实现方式,除了必须的 Button 和 Page 两个类之外,都不需要额外的类。两种实现都解决了类爆炸的问题。下面让我们对照着来看一下我们前面的分析。现在我们有:两个不同的术语以及各自的动作:信号和槽;

在一个地方(信号)可以连接零个或者多个回调函数(槽),同时也是多对多的;

焦点在于连接本身,而不是提供者或者消费者;

不需要手工为了一个连接创建新的类;

连接仍旧是类型安全的。

这五点是信号槽系统的核心,Qt 和 boost 都拥有这些特性。下面则是二者的不同之处:

Boost.SignalsQt Signals 和 Slots

一个信号就是一个对象信号只能是成员函数

发出信号类似于函数调用发出信号类似于函数调用,Qt 提供了一个 emit 关键字来完成这个操作

信号可以是全局的、局部的或者是成员对象信号只能是成员函数

任何能够访问到信号对象的代码都可以发出信号只有信号的拥有者才能发出信号

槽是任何可被调用的函数或者函数对象槽是经过特别设计的成员函数

可以有返回值,返回值可以在多个槽中使用没有返回值

同步的同步的或者队列的

非线程安全线程安全,可以跨线程使用

当且仅当槽是可追踪的时候,槽被销毁时,连接自动断开槽被销毁时,连接都会自动断开(因为所有槽都是可追踪的)

类型安全(编译器检查)类型安全(运行期检查)

参数列表必须完全一致槽可以忽略信号中多余的参数

信号、槽可以是模板信号、槽不能是模板

C++ 直接实现通过由 moc 生成的元对象实现(moc 以及元对象系统都是 C++ 直接实现的)

没有内省机制可以通过内省发现

可以通过元对象调用 连接可以从资源文件中自动推断出

最重要的是,Qt 的信号槽机制已经深深地植入到框架之中,成为不可分割的一部分。它们可以使用 Qt 专门的开发工具,例如 QtCreator,通过拖拽的方式很轻松的创建、删除、修改。它们甚至可以通过动态加载资源文件,由特定命名的对象自动动态生成。这些都是 boost 作为一个通用库所不可能提供的。

  • 0
    点赞
  • 0
    收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
©️2022 CSDN 皮肤主题:数字20 设计师:CSDN官方博客 返回首页
评论
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、C币套餐、付费专栏及课程。

余额充值