[新手园地] 用C++仿制QT的信号,槽调度

[复制链接]
3457|13
 楼主| uc_cm0 发表于 2011-11-18 10:58 | 显示全部楼层 |阅读模式
本帖最后由 hotpower 于 2012-9-22 13:17 编辑

QT上的信号,槽最简例子:
  1.     class Foo : public QObject
  2.     {
  3.         Q_OBJECT
  4.     public:
  5.         Foo(){}
  6.         int value() const { return val; }
  7.     public slots:
  8.         void setValue( int );
  9.     signals:
  10.         void valueChanged( int );
  11.     private:
  12.         int val;
  13.     };


  14.      void Foo::setValue( int v )
  15.     {
  16.         if ( v != val ) {
  17.             val = v;
  18.             emit valueChanged(v);
  19.         }
  20.     }


  21.     Foo a, b;
  22.     connect(&a, SIGNAL(valueChanged(int)), &b, SLOT(setValue(int)));
  23.     b.setValue( 11 ); // a == undefined  b == 11
  24.     a.setValue( 79 ); // a == 79         b == 79
  25.     b.value();        
 楼主| uc_cm0 发表于 2011-11-18 10:59 | 显示全部楼层
本帖最后由 uc_cm0 于 2011-11-18 11:07 编辑

用C++仿制:

  1. class Foo : public VSLOT_CLASS
  2. {
  3. public:
  4.   Foo(){};
  5.   int value() const { return val; }
  6.   
  7.   VSLOT_DeclarationIn(Foo,setValue);  //声明槽
  8.   VSIGNAL_CLASS      valueChanged;    //定义信号
  9. private:
  10.   int val;
  11. };

  12. VSLOT_ImplementationWitchParamIn(Foo,setValue,v) //槽定义
  13. {
  14.   if ( (int)v != val )     //注意:槽传递的参数类型是unsigned int
  15.   {
  16.     val = v;
  17.     valueChanged.DoSignal(v);
  18.   }
  19. }
  20.      
  21. Foo a, b;

  22. int main()
  23. {     
  24.     SIGNAL_Connect(&a.valueChanged,&b,VSLOT_OBJECT_IN(Foo,setValue));  
  25.    //连接信号与槽
  26.     b.setValue( 11 ); // a == undefined  b == 11
  27.     a.setValue( 79 ); // a == 79         b == 79
  28.     b.value();      
  29.   
  30.   while(1);
  31. }
X-Hawk 发表于 2011-11-18 12:40 | 显示全部楼层
楼主C++水平也这么高! 赞!
hotpower 发表于 2011-11-18 12:50 | 显示全部楼层
哈哈,他被9g诱拐了
 楼主| uc_cm0 发表于 2011-11-18 15:05 | 显示全部楼层
本帖最后由 uc_cm0 于 2011-11-18 16:00 编辑

注意:
1.一个信号,只能连接一个槽
2.信号触发,槽立即被调用
3.内存使用,一个信号占用2个int空间。槽只在使用时分配局部对象,占用1个int空间,使用后立即释放。另外,槽所在的对象会多用1个int空间。
Ryanhsiung 发表于 2011-11-18 18:16 | 显示全部楼层
等QT成熟了我再玩!
缥缈九哥 发表于 2011-11-18 22:19 | 显示全部楼层
QT已经够成熟了。我也想学学。哈哈。
 楼主| uc_cm0 发表于 2011-11-19 16:40 | 显示全部楼层
#include "proj_incs.h"
#include <iostream>

class A_CLASS
{
public:
  VSIGNAL_CLASS signal_1;       //定义信号
  VSIGNAL_CLASS signal_2;       //定义信号
  VSIGNAL_CLUSTER_CLASS signal_clustrt_1;
};

class B_CLASS:public VSLOT_CLASS
{
public:
   VSLOT_DeclarationIn(B_CLASS,slot_1);  //声明槽函数
   VSLOT_DeclarationIn(B_CLASS,slot_2);  //声明槽函数
};

VSLOT_ImplementationWitchParamIn(B_CLASS,slot_1,SignalParam)  //定义槽函数
{
  cout<<"slot_1 do,SignalParam="<<SignalParam<<"\r\n";
}

VSLOT_ImplementationWitchParamIn(B_CLASS,slot_2,SignalParam)  //定义槽函数
{
  cout<<"slot_2 do,SignalParam="<<SignalParam<<"\r\n";
}

A_CLASS A_OBJECT;
B_CLASS B_OBJECT;

int main()
{   
  B_OBJECT.slot_1();    //直接运行槽函数,默认参数0
  B_OBJECT.slot_2();    //直接运行槽函数,默认参数0
  
  B_OBJECT.slot_1(1);   //直接运行槽函数,带参数
  B_OBJECT.slot_2(1);   //直接运行槽函数,带参数
  
  //信号signal_1连接槽函数slot_1
  A_OBJECT.signal_1<<VSIGNAL_OBJECT(&B_OBJECT,B_CLASS,slot_1);              
  //信号signal_1触发,槽函数slot_1运行
  A_OBJECT.signal_1.DoSignal();    //默认参数
  A_OBJECT.signal_1.DoSignal(1);   //带参数
  
  //信号signal_1连接槽函数slot_2(一个信号只能连接一个槽函数,先前连接的自动断开)
  A_OBJECT.signal_1<<VSIGNAL_OBJECT(&B_OBJECT,B_CLASS,slot_2);
  //信号slot_1触发,槽函数slot_2运行
  A_OBJECT.signal_1.DoSignal();    //默认参数                                      //信号slot_1触发,槽slot_2运行
  A_OBJECT.signal_1.DoSignal(1);   //带参数
  
  //信号signal_1断开连接
  A_OBJECT.signal_1.DisConnect();                                       
  //信号slot_1触发,无槽函数运行
  A_OBJECT.signal_1.DoSignal();    //默认参数                                      
  A_OBJECT.signal_1.DoSignal(1);   //带参数
  
  //信号簇signal_clustrt_1添加槽函数slot_1
  A_OBJECT.signal_clustrt_1 += VSIGNAL_OBJECT(&B_OBJECT,B_CLASS,slot_1);  
  //信号簇触发,槽函数slot_1运行
  A_OBJECT.signal_clustrt_1.DoSignal();    //默认参数                                      
  A_OBJECT.signal_clustrt_1.DoSignal(1);   //带参数
  
  //信号簇signal_clustrt_1添加槽函数slot_2
  A_OBJECT.signal_clustrt_1 += VSIGNAL_OBJECT(&B_OBJECT,B_CLASS,slot_2);
    //信号簇触发,槽函数slot_1,槽函数slot_1都运行
  A_OBJECT.signal_clustrt_1.DoSignal();    //默认参数                                      
  A_OBJECT.signal_clustrt_1.DoSignal(1);   //带参数
  
  //信号簇signal_clustrt_1删除槽函数slot_1
  A_OBJECT.signal_clustrt_1 -= VSIGNAL_OBJECT(&B_OBJECT,B_CLASS,slot_1);
  //信号簇触发,槽函数slot_2运行
  A_OBJECT.signal_clustrt_1.DoSignal();    //默认参数                                      
  A_OBJECT.signal_clustrt_1.DoSignal(1);   //带参数
  
  //信号簇signal_clustrt_1删除槽函数slot_2
  A_OBJECT.signal_clustrt_1 -= VSIGNAL_OBJECT(&B_OBJECT,B_CLASS,slot_2);
  //信号簇触发,无槽函数运行
  A_OBJECT.signal_clustrt_1.DoSignal();    //默认参数                                      
  A_OBJECT.signal_clustrt_1.DoSignal(1);   //带参数
  
  //信号簇signal_clustrt_1添加槽函数slot_1
  A_OBJECT.signal_clustrt_1 += VSIGNAL_OBJECT(&B_OBJECT,B_CLASS,slot_1);
  //信号簇signal_clustrt_1添加槽函数slot_2
  A_OBJECT.signal_clustrt_1 += VSIGNAL_OBJECT(&B_OBJECT,B_CLASS,slot_2);
  //信号簇触发,槽函数slot_1,槽函数slot_1都运行
  A_OBJECT.signal_clustrt_1.DoSignal();    //默认参数                                      
  A_OBJECT.signal_clustrt_1.DoSignal(1);   //带参数
  
  //删除所有槽函数
  A_OBJECT.signal_clustrt_1.Clear();
  //信号簇触发,无槽函数运行
  A_OBJECT.signal_clustrt_1.DoSignal();    //默认参数                                      
  A_OBJECT.signal_clustrt_1.DoSignal(1);   //带参数
  
  while(1);
}
 楼主| uc_cm0 发表于 2011-11-19 16:44 | 显示全部楼层
改进:
1.信号连接槽,使用<<符号重载
2.增加信号簇,信号簇可以连接多个槽,使用+=符号重载,删除信号簇的槽,用-=符号重载。清空信号槽,用Clear().
3.信号簇使用队列,动态分配内存。
缥缈九哥 发表于 2011-11-20 08:57 | 显示全部楼层
要顶起。。。向高手们多学习学习C++。。。
 楼主| uc_cm0 发表于 2011-11-26 08:43 | 显示全部楼层
本帖最后由 uc_cm0 于 2011-11-26 08:46 编辑

信号槽增加状态机


#include "proj_incs.h"
#include <iostream>

class A_CLASS:public VSTATE_SCHED_CLASS
{
public:
  VSIGNAL_CLASS signal_1;                    //定义信号signal_1
  VSIGNAL_CLASS signal_2;                    //定义信号signal_2     
  
  VSTATE_DeclarationIn(A_CLASS,state_1);     //声明一个状态state_1
  VSTATE_DeclarationIn(A_CLASS,state_2);     //声明一个状态state_2
  VSLOT_DeclarationIn(A_CLASS,slot_1);       //声明槽函数slot_1
  VSLOT_DeclarationIn(A_CLASS,slot_2);       //声明槽函数slot_2
};

VSLOT_ImplementationIn(A_CLASS,slot_1)       //A_CLASS槽函数slot_1实现
{
  cout<<"A_OBJECT运行槽函数slot_1,参数VParam="<<(uint32)VParam<<"\r\n";
}

VSLOT_ImplementationIn(A_CLASS,slot_2)       //A_CLASS槽函数slot_2实现
{
  cout<<"A_OBJECT运行槽函数slot_2,参数VParam="<<(uint32)VParam<<"\r\n";
}

class B_CLASS:public VSTATE_SCHED_CLASS
{
public:
  VSIGNAL_CLASS signal_1;                    //定义信号signal_1
  VSIGNAL_CLASS signal_2;                    //定义信号signal_2     
  
  VSTATE_DeclarationIn(B_CLASS,state_1);     //声明一个状态state_1
  VSTATE_DeclarationIn(B_CLASS,state_2);     //声明一个状态state_2
  VSLOT_DeclarationIn(B_CLASS,slot_1);       //声明槽函数slot_1
  VSLOT_DeclarationIn(B_CLASS,slot_2);       //声明槽函数slot_2
};

VSLOT_ImplementationIn(B_CLASS,slot_1)       //B_CLASS槽函数slot_1实现
{
  cout<<"B_OBJECT运行槽函数slot_1,参数VParam="<<(uint32)VParam<<"\r\n";
}

VSLOT_ImplementationIn(B_CLASS,slot_2)       //B_CLASS槽函数slot_2实现
{
  cout<<"B_OBJECT运行槽函数slot_2,参数VParam="<<(uint32)VParam<<"\r\n";
}


A_CLASS A_OBJECT;
B_CLASS B_OBJECT;

VSTATE_ImplementationIn(A_CLASS,state_1)      //A_CLASS状态state_1实现
{
  cout<<"A_OBJECT进入状态state_1\r\n";
  
  cout<<"A_OBJECT触发信号signal_1,参数VParam=1\r\n";
  this->signal_1.DoSignal(1);
   
  cout<<"A_OBJECT设置下一次运行状态state_2\r\n";
  *this<<VSTATE_OBJECT_IN(A_CLASS,state_2);

  cout<<"A_OBJECT退出状态state_1\r\n";  
}

VSTATE_ImplementationIn(A_CLASS,state_2)       //A_CLASS状态state_2实现
{
  cout<<"A_OBJECT进入状态state_2\r\n";
  
  cout<<"A_OBJECT触发信号signal_2,参数VParam=2\r\n";
  this->signal_2.DoSignal(2);
  
  cout<<"A_OBJECT设置下一次运行状态state_1\r\n";
  *this<<VSTATE_OBJECT_IN(A_CLASS,state_1);
  
  cout<<"A_OBJECT退出状态state_2\r\n";
}

VSTATE_ImplementationIn(B_CLASS,state_1)       //B_CLASS状态state_1实现
{
  cout<<"B_OBJECT进入状态state_1\r\n";
  
  cout<<"B_OBJECT触发信号signal_1,参数VParam=1\r\n";
  this->signal_1.DoSignal(1);
   
  cout<<"B_OBJECT设置下一次运行状态state_2\r\n";
  *this<<VSTATE_OBJECT_IN(B_CLASS,state_2);
  
  cout<<"B_OBJECT退出状态state_1\r\n";
}

VSTATE_ImplementationIn(B_CLASS,state_2)           //B_CLASS状态state_2实现
{
  cout<<"B_OBJECT进入状态state_2\r\n";
  
  cout<<"B_OBJECT触发信号signal_2,参数VParam=2\r\n";
  this->signal_2.DoSignal(2);
  
  cout<<"B_OBJECT设置下一次运行状态state_1\r\n";
  *this<<VSTATE_OBJECT_IN(B_CLASS,state_1);
   
  cout<<"B_OBJECT退出状态state_2\r\n";
}

int main()
{
  cout<<"A_OBJECT初始化\r\n";
  cout<<"A_OBJECT设置初始状态state_1\r\n";
  A_OBJECT<<VSTATE_OBJECT_IN(A_CLASS,state_1);
  
  cout<<"A_OBJECT信号signal_1连接B_OBJECT槽函数slot_1\r\n";
  A_OBJECT.signal_1<<VSIGNAL_OBJECT(&B_OBJECT,B_CLASS,slot_1);
  
  cout<<"A_OBJECT信号signal_2连接B_OBJECT槽函数slot_2\r\n";
  A_OBJECT.signal_2<<VSIGNAL_OBJECT(&B_OBJECT,B_CLASS,slot_2);
  cout<<"\r\n";
  
  cout<<"B_OBJECT初始化\r\n";
  cout<<"B_OBJECT设置初始状态state_1\r\n";
  B_OBJECT<<VSTATE_OBJECT_IN(B_CLASS,state_1);
  
  cout<<"B_OBJECT信号signal_1连接A_OBJECT槽函数slot_1\r\n";
  B_OBJECT.signal_1<<VSIGNAL_OBJECT(&A_OBJECT,A_CLASS,slot_1);
  
  cout<<"B_OBJECT信号signal_2连接A_OBJECT槽函数slot_2\r\n";
  B_OBJECT.signal_2<<VSIGNAL_OBJECT(&A_OBJECT,A_CLASS,slot_2);
  cout<<"\r\n";
  
  cout<<"运行主循环while(1)\r\n";
  cout<<"\r\n";
  
  while(1)
  {
    cout<<"运行A_OBJECT调度\r\n";
    A_OBJECT.Do();
    cout<<"\r\n";
   
    cout<<"运行B_OBJECT调度\r\n";
    B_OBJECT.Do();
    cout<<"\r\n";   
  }
}
 楼主| uc_cm0 发表于 2011-11-26 08:43 | 显示全部楼层
A_OBJECT初始化
A_OBJECT设置初始状态state_1
A_OBJECT信号signal_1连接B_OBJECT槽函数slot_1
A_OBJECT信号signal_2连接B_OBJECT槽函数slot_2

B_OBJECT初始化
B_OBJECT设置初始状态state_1
B_OBJECT信号signal_1连接A_OBJECT槽函数slot_1
B_OBJECT信号signal_2连接A_OBJECT槽函数slot_2

运行主循环while(1)

运行A_OBJECT调度
A_OBJECT进入状态state_1
A_OBJECT触发信号signal_1,参数VParam=1
B_OBJECT运行槽函数slot_1,参数VParam=1
A_OBJECT设置下一次运行状态state_2
A_OBJECT退出状态state_1

运行B_OBJECT调度
B_OBJECT进入状态state_1
B_OBJECT触发信号signal_1,参数VParam=1
A_OBJECT运行槽函数slot_1,参数VParam=1
B_OBJECT设置下一次运行状态state_2
B_OBJECT退出状态state_1

运行A_OBJECT调度
A_OBJECT进入状态state_2
A_OBJECT触发信号signal_2,参数VParam=2
B_OBJECT运行槽函数slot_2,参数VParam=2
A_OBJECT设置下一次运行状态state_1
A_OBJECT退出状态state_2

运行B_OBJECT调度
B_OBJECT进入状态state_2
B_OBJECT触发信号signal_2,参数VParam=2
A_OBJECT运行槽函数slot_2,参数VParam=2
B_OBJECT设置下一次运行状态state_1
B_OBJECT退出状态state_2

运行A_OBJECT调度
A_OBJECT进入状态state_1
A_OBJECT触发信号signal_1,参数VParam=1
B_OBJECT运行槽函数slot_1,参数VParam=1
A_OBJECT设置下一次运行状态state_2
A_OBJECT退出状态state_1

运行B_OBJECT调度
B_OBJECT进入状态state_1
B_OBJECT触发信号signal_1,参数VParam=1
A_OBJECT运行槽函数slot_1,参数VParam=1
B_OBJECT设置下一次运行状态state_2
B_OBJECT退出状态state_1

运行A_OBJECT调度
A_OBJECT进入状态state_2
A_OBJECT触发信号signal_2,参数VParam=2
B_OBJECT运行槽函数slot_2,参数VParam=2
A_OBJECT设置下一次运行状态state_1
A_OBJECT退出状态state_2

运行B_OBJECT调度
B_OBJECT进入状态state_2
B_OBJECT触发信号signal_2,参数VParam=2
A_OBJECT运行槽函数slot_2,参数VParam=2
B_OBJECT设置下一次运行状态state_1
B_OBJECT退出状态state_2

运行A_OBJECT调度
A_OBJECT进入状态state_1
A_OBJECT触发信号signal_1,参数VParam=1
B_OBJECT运行槽函数slot_1,参数VParam=1
A_OBJECT设置下一次运行状态state_2
A_OBJECT退出状态state_1

运行B_OBJECT调度
B_OBJECT进入状态state_1
B_OBJECT触发信号signal_1,参数VParam=1
A_OBJECT运行槽函数slot_1,参数VParam=1
B_OBJECT设置下一次运行状态state_2
B_OBJECT退出状态state_1

运行A_OBJECT调度
A_OBJECT进入状态state_2
A_OBJECT触发信号signal_2,参数VParam=2
B_OBJECT运行槽函数slot_2,参数VParam=2
A_OBJECT设置下一次运行状态state_1
A_OBJECT退出状态state_2

运行B_OBJECT调度
B_OBJECT进入状态state_2
B_OBJECT触发信号signal_2,参数VParam=2
A_OBJECT运行槽函数slot_2,参数VParam=2
B_OBJECT设置下一次运行状态state_1
B_OBJECT退出状态state_2

运行A_OBJECT调度
A_OBJECT进入状态state_1
A_OBJECT触发信号signal_1,参数VParam=1
B_OBJECT运行槽函数slot_1,参数VParam=1
A_OBJECT设置下一次运行状态state_2
A_OBJECT退出状态state_1

运行B_OBJECT调度
B_OBJECT进入状态state_1
B_OBJECT触发信号signal_1,参数VParam=1
A_OBJECT运行槽函数slot_1,参数VParam=1
B_OBJECT设置下一次运行状态state_2
B_OBJECT退出状态state_1

运行A_OBJECT调度
A_OBJECT进入状态state_2
A_OBJECT触发信号signal_2,参数VParam=2
B_OBJECT运行槽函数slot_2,参数VParam=2
A_OBJECT设置下一次运行状态state_1
A_OBJECT退出状态state_2

运行B_OBJECT调度
B_OBJECT进入状态state_2
B_OBJECT触发信号signal_2,参数VParam=2
A_OBJECT运行槽函数slot_2,参数VParam=2
B_OBJECT设置下一次运行状态state_1
B_OBJECT退出状态state_2

运行A_OBJECT调度
A_OBJECT进入状态state_1
A_OBJECT触发信号signal_1,参数VParam=1
B_OBJECT运行槽函数slot_1,参数VParam=1
A_OBJECT设置下一次运行状态state_2
A_OBJECT退出状态state_1

运行B_OBJECT调度
B_OBJECT进入状态state_1
B_OBJECT触发信号signal_1,参数VParam=1
A_OBJECT运行槽函数slot_1,参数VParam=1
B_OBJECT设置下一次运行状态state_2
B_OBJECT退出状态state_1

运行A_OBJECT调度
A_OBJECT进入状态state_2
A_OBJECT触发信号signal_2,参数VParam=2
B_OBJECT运行槽函数slot_2,参数VParam=2
A_OBJECT设置下一次运行状态state_1
A_OBJECT退出状态state_2

运行B_OBJECT调度
B_OBJECT进入状态state_2
B_OBJECT触发信号signal_2,参数VParam=2
A_OBJECT运行槽函数slot_2,参数VParam=2
B_OBJECT设置下一次运行状态state_1
B_OBJECT退出状态state_2

运行A_OBJECT调度
A_OBJECT进入状态state_1
A_OBJECT触发信号signal_1,参数VParam=1
B_OBJECT运行槽函数slot_1,参数VParam=1
A_OBJECT设置下一次运行状态state_2
A_OBJECT退出状态state_1

运行B_OBJECT调度
B_OBJECT进入状态state_1
B_OBJECT触发信号signal_1,参数VParam=1
A_OBJECT运行槽函数slot_1,参数VParam=1
B_OBJECT设置下一次运行状态state_2
B_OBJECT退出状态state_1

运行A_OBJECT调度
A_OBJECT进入状态state_2
A_OBJECT触发信号signal_2,参数VParam=2
B_OBJECT运行槽函数slot_2,参数VParam=2
A_OBJECT设置下一次运行状态state_1
A_OBJECT退出状态state_2

运行B_OBJECT调度
B_OBJECT进入状态state_2
B_OBJECT触发信号signal_2,参数VParam=2
A_OBJECT运行槽函数slot_2,参数VParam=2
B_OBJECT设置下一次运行状态state_1
B_OBJECT退出状态state_2

运行A_OBJECT调度
A_OBJECT进入状态state_1
A_OBJECT触发信号signal_1,参数VParam=1
B_OBJECT运行槽函数slot_1,参数VParam=1
A_OBJECT设置下一次运行状态state_2
A_OBJECT退出状态state_1

运行B_OBJECT调度
B_OBJECT进入状态state_1
B_OBJECT触发信号signal_1,参数VParam=1
A_OBJECT运行槽函数slot_1,参数VParam=1
B_OBJECT设置下一次运行状态state_2
B_OBJECT退出状态state_1

运行A_OBJECT调度
A_OBJECT进入状态state_2
A_OBJECT触发信号signal_2,参数VParam=2
B_OBJECT运行槽函数slot_2,参数VParam=2
A_OBJECT设置下一次运行状态state_1
A_OBJECT退出状态state_2

运行B_OBJECT调度
B_OBJECT进入状态state_2
B_OBJECT触发信号signal_2,参数VParam=2
A_OBJECT运行槽函数slot_2,参数VParam=2
B_OBJECT设置下一次运行状态state_1
B_OBJECT退出状态state_2
乡村男孩 发表于 2011-11-26 08:49 | 显示全部楼层
膜拜高人
mcs8098 发表于 2011-12-20 12:44 | 显示全部楼层
支持!:lol
您需要登录后才可以回帖 登录 | 注册

本版积分规则

个人签名:上官金虹:转战C++

0

主题

32

帖子

0

粉丝
快速回复 在线客服 返回列表 返回顶部