打印
[新手园地]

用C++仿制QT的信号,槽调度

[复制链接]
2471|13
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
uc_cm0|  楼主 | 2011-11-18 10:58 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
本帖最后由 hotpower 于 2012-9-22 13:17 编辑

QT上的信号,槽最简例子:
    class Foo : public QObject
    {
        Q_OBJECT
    public:
        Foo(){}
        int value() const { return val; }
    public slots:
        void setValue( int );
    signals:
        void valueChanged( int );
    private:
        int val;
    };


     void Foo::setValue( int v )
    {
        if ( v != val ) {
            val = v;
            emit valueChanged(v);
        }
    }


    Foo a, b;
    connect(&a, SIGNAL(valueChanged(int)), &b, SLOT(setValue(int)));
    b.setValue( 11 ); // a == undefined  b == 11
    a.setValue( 79 ); // a == 79         b == 79
    b.value();        

相关帖子

沙发
uc_cm0|  楼主 | 2011-11-18 10:59 | 只看该作者
本帖最后由 uc_cm0 于 2011-11-18 11:07 编辑

用C++仿制:

class Foo : public VSLOT_CLASS
{
public:
  Foo(){};
  int value() const { return val; }
  
  VSLOT_DeclarationIn(Foo,setValue);  //声明槽
  VSIGNAL_CLASS      valueChanged;    //定义信号
private:
  int val;
};

VSLOT_ImplementationWitchParamIn(Foo,setValue,v) //槽定义
{
  if ( (int)v != val )     //注意:槽传递的参数类型是unsigned int
  {
    val = v;
    valueChanged.DoSignal(v);
  }
}
     
Foo a, b;

int main()
{     
    SIGNAL_Connect(&a.valueChanged,&b,VSLOT_OBJECT_IN(Foo,setValue));  
   //连接信号与槽
    b.setValue( 11 ); // a == undefined  b == 11
    a.setValue( 79 ); // a == 79         b == 79
    b.value();      
  
  while(1);
}

使用特权

评论回复
板凳
X-Hawk| | 2011-11-18 12:40 | 只看该作者
楼主C++水平也这么高! 赞!

使用特权

评论回复
地板
hotpower| | 2011-11-18 12:50 | 只看该作者
哈哈,他被9g诱拐了

使用特权

评论回复
5
uc_cm0|  楼主 | 2011-11-18 15:05 | 只看该作者
本帖最后由 uc_cm0 于 2011-11-18 16:00 编辑

注意:
1.一个信号,只能连接一个槽
2.信号触发,槽立即被调用
3.内存使用,一个信号占用2个int空间。槽只在使用时分配局部对象,占用1个int空间,使用后立即释放。另外,槽所在的对象会多用1个int空间。

使用特权

评论回复
6
Ryanhsiung| | 2011-11-18 18:16 | 只看该作者
等QT成熟了我再玩!

使用特权

评论回复
7
缥缈九哥| | 2011-11-18 22:19 | 只看该作者
QT已经够成熟了。我也想学学。哈哈。

使用特权

评论回复
8
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);
}

使用特权

评论回复
9
uc_cm0|  楼主 | 2011-11-19 16:44 | 只看该作者
改进:
1.信号连接槽,使用<<符号重载
2.增加信号簇,信号簇可以连接多个槽,使用+=符号重载,删除信号簇的槽,用-=符号重载。清空信号槽,用Clear().
3.信号簇使用队列,动态分配内存。

使用特权

评论回复
10
缥缈九哥| | 2011-11-20 08:57 | 只看该作者
要顶起。。。向高手们多学习学习C++。。。

使用特权

评论回复
11
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";   
  }
}

使用特权

评论回复
12
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

使用特权

评论回复
13
乡村男孩| | 2011-11-26 08:49 | 只看该作者
膜拜高人

使用特权

评论回复
14
mcs8098| | 2011-12-20 12:44 | 只看该作者
支持!:lol

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

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

0

主题

32

帖子

0

粉丝