Libsigc++库的使用

概述

通常在图形用户界面程序中,我们希望检测事件的代码与处理事件的代码能够分开独立出来。我们可以使用回调函数的机制,注册函数指针来注册相关的处理函数,不过,在C++中,我们可以使用类型安全的库libsigc++。

Libsigc++库中提出了槽的概念,熟悉Qt的朋友应该对槽的概念不陌生,它其实是指向一个可作为回调的函数的引用,以下三种类型的函数都可作为槽:

1. 普通函数。

2. 重载了operator()的函数子对象(类)。

3. 如果对象所属的类继承了sigc::trackable, 它的成员函数也可以作为槽。

针对第三种类型的函数,libsigc++库提供了sigc::ptr_func()和sigc::mem_func()为分别从类的静态函数和对象的成员函数中创建槽。返回值类型是signal::slot,可通过emit()或operator()调用。另外,libsigc++也提出了信号的概念signals,它是模板类型sigc::signal实例, 可将信号与槽连接起来,当emit信号时,所有连接到信号的槽将会执行。

一个简单的示例

Signal发送方:

class AlienDetector

{

public:

AlienDetector()

{

}

void run()

{

cout<<"AlienDetector is running"<<endl;

//        signal_detected.emit();

signal_detected();

}

sigc::signal<void> signal_detected;

};

槽函数定义,与信号的返回值类型一致:

void warn_people()

{

cout<<"There are aliens in the carpark!"<<endl;

}

连接信号和槽:

int main()

{

AlienDetector mydetector;

mydetector.signal_detected.connect(sigc::ptr_fun(warn_people));

mydetector.run();

return 0;

}

头文件包含:

#include <iostream>

#include <sigc++/sigc++.h>

编译:

g++ example1.cc -o example1 `pkg-config --cflags --libs sigc++-2.0`

使用成员函数作为槽

上述例子演示了普通函数作为槽函数,接下来的例子将显示如何将成员函数作为槽使用。

提供槽函数的类定义如下,必须从sigc::trackable继承:

class AlienAlerter : public sigc::trackable

{

public:

AlienAlerter(char const* servername)

{

srvname = string(servername);

}

void alert()

{

cout<<"server name: "<<srvname<<endl;

}

private:

// ...

string srvname;

};

连接信号和槽

int main()

{

AlienDetector mydetector;

AlienAlerter  myalerter("localhost");

mydetector.signal_detected.connect(sigc::mem_fun(myalerter, &AlienAlerter::alert));

mydetector.run();

return 0;

}

带参数的信号

信号的类型sigc::signal的模板参数中第一个是返回值类型,后面都是信号参数的类型,如:

sigc::signal<void, std::string>

那么对应的槽函数声明也必须为返回值为void, 接受一个参数为std::string的函数,即:

void warn_people(std::string where)

{

cout << "There are aliens in " << where << "!" << endl;

}

如前述AlienDetector类的声明修改如下:

class AlienDetector

{

public:

AlienDetector();

void run();

sigc::signal<void, std::string> signal_detected; // changed

};

连接信号和槽:

int main()

{

AlienDetector mydetector;

mydetector.signal_detected.connect( sigc::ptr_fun(warn_people) );

mydetector.run();

return 0;

}

断开信号和槽之间的连接

信号sigc::signal的connect方法的返回值类型为:sigc::connection, 它提供了一个disconnect函数来断开信号和槽之间的连接。

高级话题

重新绑定(rebinding)

当信号与槽的类型不匹配时,连接时会出现编译错误。为了解决这种不匹配的情况,我们可以利用sigc::bind进行重绑定,便信号与槽之间的类型能够重新匹配。

假设我们定义了除返回值外, 不带任何参数的信号,这样与之连接的槽函数也不能接受任何参数。如果我们要利用一个已经写好的并需要传入参数的函数,我们可以通过sigc::bind作些处理,如下所示:

myaliendetector.signal_detected.connect(sigc::bind( sigc::ptr_fun(warn_people), "the carpark" ) );

其中sigc::bind(slot, arg), 如果槽函数接受多个参数,那么arg指的是最右边那个参数。

另外,返回值的类型也可以通过类似的方式重新绑定:

sigc::bind_return(slot, returnvalue)

反过来,如果我们要利用一个已存在的函数作为槽函数,它接受一个参数,但是信号要求槽函数不接受任何参数,可以通过如下方式进行重新绑定:

myaliendetector.signal_detected.connect( sigc::hide<std::string>( sigc::ptr_fun(warn_people) ) );

,如果有多个参数,如上写法隐藏的是最右边的参数。

类型重定义(Retyping)

另一种情况是,当信号接受一个整型参数,但我们想让它与一个接受双精度类型的槽函数连接,这时需要进行类型重定义,可以通过sigc::retype模板类型,它与sigc::signal的模板参数一样。

void dostuff(double foo)

{

}

sigc::signal<void,int> asignal;

asignal.connect(  sigc::retype<void, int>( slot(&dostuff) )  );

当只是返回类型不同时,则只需指定返回类型参数。

转载于:https://my.oschina.net/fuyajun1983cn/blog/263851

libsigc++库的使用相关推荐

  1. kurento代码分析(一)C++与C的交互

     简单阅读了下kurento的代码,因为自身也是小白,许多地方也是一知半解的.它的代码不容易理清逻辑,它采用gstreamer的流媒体处理框架,信令处理部分主要由c++负责,而媒体处理部分则由c层的g ...

  2. Windows API参考大全

    第一章 Win32 API概论 1.1为什么使用 Wu32 API 在Windows程序设计领域处于发展初期时,Windows程序员可使用的编程工具唯有API 函数.这些函数在程序员手中犹如" ...

  3. 中标麒麟 NeoKylin-SDK 里都有哪些库文件

    ** 中标麒麟 NeoKylin-SDK 里都有哪些库文件 ** 下边是中标麒麟 1-8 和14的安装包内容.希望对中标麒麟开发的同学能有些帮助. [root@bogon NeoKylin-SDK]# ...

  4. c++ 工具库 (zz)

    下面是收集的一些开发工具包,主要是C/C++方面的,涉及图形.图像.游戏.人工智能等各个方面,感觉是一个比较全的资源.供参考! 原文的出处:http://www.codemonsters.de/hom ...

  5. 【C/C++开发】c++ 工具库 (zz)

    下面是收集的一些开发工具包,主要是C/C++方面的,涉及图形.图像.游戏.人工智能等各个方面,感觉是一个比较全的资源.供参考!  原文的出处:http://www.codemonsters.de/ho ...

  6. C++ 100款开源界面库——内容细节(现在有变动)不必深究,普及就好

    C++ 100款开源界面库 (10) from:http://www.cnblogs.com/Alberl/p/3375162.html (声明:Alberl以后说到开源库,一般都是指著名的.或者不著 ...

  7. 仿迅雷播放器教程 -- C++ 100款开源界面库 (10)

    (声明:Alberl以后说到开源库,一般都是指著名的.或者不著名但维护至少3年以上的.那些把代码一扔就没下文的,Alberl不称之为开源库,只称为开源代码.这里并不是贬低,像Alberl前面那个系列的 ...

  8. Go 编译的可执行文件是否有动态库链接?

    Go 引用了其他包的话,是将引用的包都编译进去.用 ldd 看几个 Go 编译出来的二进制程序有的没有动态链接库的使用.但是有的又有引用动态链接库,这个是为什么? 回答:Go 默认是开启 CGO_EN ...

  9. Go 学习笔记(78)— Go 标准库 net/http 创建服务端(接收 GET、POST 请求)

    使用 net/http 标准库创建一个 http 的 restful api 的服务端,用来处理 GET.POST 等请求. 源代码如下: package mainimport ("enco ...

最新文章

  1. cocos2d-x android 黑屏,cocos2d-x-3.8生成android 的apk后真机测试出现黑屏
  2. php微服务架构设计模式,《微服务架构设计模式》读书笔记---第十一章:开发面向生产环境的微服务应用...
  3. 4.1 Tensorflow:卷积函数
  4. 李开复悔过:把运营微博当人生,把获取粉丝当游戏
  5. GPUImage API 文档之GPUImagePicture类
  6. “约见”面试官系列之常见面试题第十四篇之所有数据类型(建议收藏)
  7. SVN工作笔记001---svn删除已经上传的文件
  8. 自己动手写个小框架之三
  9. [转载] python 去除字符串的标点符号 用_Python成为专业人士笔记–String字符串方法
  10. 【转】Android 平台下使用 i2c-tools
  11. sql server 2005_全文目录
  12. 使用 Android 签名 APK
  13. Linux怎么运行lisp,Lisp - Ubuntu 中的编程语言_Linux编程_Linux公社-Linux系统门户网站...
  14. R3Det: Refined Single-Stage Detector with Feature Refinementfor Rotating Object论文学习
  15. 互联网自动化赚钱的方法
  16. java中length 的用法
  17. 常用SQL语句 - 基于MySQL数据库
  18. Android开发——底部导航栏设计
  19. 你的企业是否需要首席数字官?
  20. [zz]各大IT公司待遇

热门文章

  1. C#中Delegate和Event以及它们的区别(转载)
  2. 自助服务台——多渠道触发运维工单
  3. 一天学习一点之express demo
  4. 软件测试2019:第四次作业
  5. 多态 oc c++ 与oc category
  6. python 获取文件大小,创建时间和访问时间
  7. Oracle 跨库 查询 复制表数据
  8. Graphlab实现分析:图的存储一
  9. lb集群lvs的3种模式
  10. 代码编辑神器VIM(附我写acm程序时的配置)(转)