一文读懂Qt信号与槽的机制

        Qt的信号与槽主要是为了对象之间的信号传递,以达到某种交互操作的功能。我按照自己的理解逐步实现这样的效果。

步骤一:

        第一个类(接收者)的成员函数实现某种功能,第二个类(发送者)定义一个对象指针,初始化后达到间接访问类1(接收者)的成员函数。运行后显示:I am a receiver!

#include <iostream>
using namespace std;

class Receiver
{
public:
    void show()
    {
        cout <<"I am a receiver!"<<endl;
    }
};

class Transimiter
{
public:
    Receiver * p_receiver;
};


int main()
{
    Transimiter t1;
    Receiver r1;
    t1.p_receiver=&r1;
    t1.p_receiver->show();
    return 0;
}

步骤二:

        不能把所有的事情都让类的成员函数去处理,因为没有人知道未来会添加哪些功能,所以把接收者中定义的show函数改成一个函数指针会更合理。这样可以在接收者初始化对象的时候赋予具体的函数地址,完成具体的功能。运行结果:

I am a slot_show function!
I am a slot_print function!

#include <iostream>
using namespace std;

class Receiver
{
public:
    void (*fun)();//函数指针
    Receiver(void (*pfun)())
    {
        this->fun=pfun;//函数指针初始化
    }
};

void slot_show()
{
    cout<<"I am a slot_show function!"<<endl;
}
void slot_print()
{
    cout<<"I am a slot_print function!"<<endl;
}

class Transimiter
{
public:
    Receiver * p_receiver;
};


int main()
{
    Transimiter t1;
    Receiver r1(&slot_show);//定义两个不同的接收者对象
    Receiver r2(&slot_print);
    t1.p_receiver=&r1;
    t1.p_receiver->fun();

    t1.p_receiver=&r2;
    t1.p_receiver->fun();
    return 0;
}

步骤三:

        为了解决一个发送者对象和多个接收者对象产生关系的问题,发送者对象应该用一个指针数组保存所有的接收者,我的数组大小为2。程序的运行结果和上面一样。

#include <iostream>
using namespace std;

class Receiver
{
public:
    void (*fun)();//函数指针
    Receiver(void (*pfun)())
    {
        this->fun=pfun;//函数指针初始化
    }
};

void slot_show()
{
    cout<<"I am a slot_show function!"<<endl;
}
void slot_print()
{
    cout<<"I am a slot_print function!"<<endl;
}

class Transimiter
{
public:
    Receiver * p_receiver[2];
};


int main()
{
    Transimiter t1;
    Receiver r1(&slot_show);//定义两个不同的接收者对象
    Receiver r2(&slot_print);
    t1.p_receiver[0]=&r1;
    t1.p_receiver[1]=&r2;
    t1.p_receiver[0]->fun();
    t1.p_receiver[1]->fun();
    return 0;
}

步骤四:

       有关发送者对象的信号发送,应当有一个专门的成员函数集中处理, 所以程序做一点修正,运行结果不变,如下:

#include <iostream>
using namespace std;

class Receiver
{
public:
    void (*fun)();//函数指针
    Receiver(void (*pfun)())
    {
        this->fun=pfun;//函数指针初始化
    }
};

void slot_show()
{
    cout<<"I am a slot_show function!"<<endl;
}
void slot_print()
{
    cout<<"I am a slot_print function!"<<endl;
}

class Transimiter
{
public:
    Receiver * p_receiver[2];
public:
    void send_message()
    {
        this->p_receiver[0]->fun();
        this->p_receiver[1]->fun();
    }
};


int main()
{
    Transimiter t1;
    Receiver r1(&slot_show);//定义两个不同的接收者对象
    Receiver r2(&slot_print);
    t1.p_receiver[0]=&r1;
    t1.p_receiver[1]=&r2;
    t1.send_message();

    return 0;
}

步骤五:

        上面的程序发送的消息是空的,我用一个整型的数字代表一个合法的消息,程序稍作修改,运行结果如下:

I am a slot_show function!
num:100
I am a slot_print function! 
num:100

#include <iostream>
using namespace std;

class Receiver
{
public:
    void (*fun)(int);//函数指针
    Receiver(void (*pfun)(int))
    {
        this->fun=pfun;//函数指针初始化
    }
};

void slot_show(int num)
{
    cout<<"I am a slot_show function!"<<endl;
    cout<<"num:"<<num<<endl;
}
void slot_print(int num)
{
    cout<<"I am a slot_print function!"<endl;
    cout<<"num:"<<num<<endl;
}

class Transimiter
{
public:
    Receiver * p_receiver[2];
public:
    void send_message(int num)
    {
        this->p_receiver[0]->fun(num);
        this->p_receiver[1]->fun(num);
    }
};


int main()
{
    Transimiter t1;
    Receiver r1(&slot_show);//定义两个不同的接收者对象
    Receiver r2(&slot_print);
    t1.p_receiver[0]=&r1;
    t1.p_receiver[1]=&r2;
    t1.send_message(100);

    return 0;
}

步骤六:

        上面的程序中发送者和接收者之间建立联系的过程不够形象,我用一个函数命名为管道连接,管理对象之间的通信。安全起见,同时把发送者对象里面的指针数组从公用属性改为私有属性。

#include <iostream>
using namespace std;

class Receiver
{
public:
    void (*fun)(int);//函数指针
    Receiver(void (*pfun)(int))
    {
        this->fun=pfun;//函数指针初始化
    }
};

void slot_show(int num)
{
    cout<<"I am a slot_show function!"<<endl;
    cout<<"num:"<<num<<endl;
}
void slot_print(int num)
{
    cout<<"I am a slot_print function!"<<endl;
    cout<<"num:"<<num<<endl;
}

class Transimiter
{
private://成员变量改为私有属性
    Receiver * p_receiver[2];
public:
    void send_message(int num)
    {
        this->p_receiver[0]->fun(num);
        this->p_receiver[1]->fun(num);
    }
    void connect_pipe(Receiver *pR,int num)//建立管道连接
    {
      this->p_receiver[num]=pR;
    }
};


int main()
{
    Transimiter t1;
    Receiver r1(&slot_show);//定义两个不同的接收者对象
    Receiver r2(&slot_print);
    t1.connect_pipe(&r1,0);
    t1.connect_pipe(&r2,1);
    t1.send_message(100);
    return 0;
}

步骤七:

        由于接受者的个数也是不确定的,因此不能把数组写死,于是我采用一个向量vector记录接收者对象的指针,相关的函数或变量做一点点修改,运行结果如下:

I am a slot_show function!
num:100
I am a slot_print function!
num:100
I am a slot_print function!
num:100

#include <iostream>
#include <vector>
using namespace std;

class Receiver
{
public:
    void (*fun)(int);//函数指针
    Receiver(void (*pfun)(int))
    {
        this->fun=pfun;//函数指针初始化
    }
};

void slot_show(int num)
{
    cout<<"I am a slot_show function!"<<endl;
    cout<<"num:"<<num<<endl;
}
void slot_print(int num)
{
    cout<<"I am a slot_print function!"<<endl;
    cout<<"num:"<<num<<endl;
}

class Transimiter
{
private://成员变量改为私有属性
    vector <Receiver*> receiver_v;
public:
    void send_message(int num)
    {
        for(vector <Receiver*>::iterator it=receiver_v.begin();it!=receiver_v.end();it++)//遍历器
        {
            (*it)->fun(num);//(*it)为实际的元素值
        }

    }
    void connect_pipe(Receiver *pR)//建立管道连接
    {
      this->receiver_v.push_back(pR);
    }
};


int main()
{
    Transimiter t1;
    Receiver r1(&slot_show);//定义两个不同的接收者对象
    Receiver r2(&slot_print);
    Receiver r3(&slot_print);
    t1.connect_pipe(&r1);
    t1.connect_pipe(&r2);
    t1.connect_pipe(&r3);
    t1.send_message(100);
    return 0;
}

步骤八:

        添加一个断开连接的函数,修改代码如下:

#include <iostream>
#include <vector>
using namespace std;

class Receiver
{
public:
    void (*fun)(int);//函数指针
    Receiver(void (*pfun)(int))
    {
        this->fun=pfun;//函数指针初始化
    }
};

void slot_show(int num)
{
    cout<<"I am a slot_show function!"<<endl;
    cout<<"num:"<<num<<endl;
}
void slot_print(int num)
{
    cout<<"I am a slot_print function!"<<endl;
    cout<<"num:"<<num<<endl;
}

class Transimiter
{
private://成员变量改为私有属性
    vector <Receiver*> receiver_v;
public:
    void send_message(int num)
    {
        for(vector <Receiver*>::iterator it=receiver_v.begin();it!=receiver_v.end();it++)//遍历器
        {
            (*it)->fun(num);//(*it)为实际的元素值
        }

    }
    void connect_pipe(Receiver *pR)//建立管道连接
    {
      this->receiver_v.push_back(pR);
    }
    void disconnect_pipe(Receiver *pR)
    {
        for(vector <Receiver*>::iterator it=receiver_v.begin();it!=receiver_v.end();it++)//遍历器
        {
            if((*it)==pR)
            {
                this->receiver_v.erase(it);
            }
        }


    }
};


int main()
{
    Transimiter t1;
    Receiver r1(&slot_show);//定义两个不同的接收者对象
    Receiver r2(&slot_print);
    Receiver r3(&slot_print);
    t1.connect_pipe(&r1);
    t1.connect_pipe(&r2);
    t1.connect_pipe(&r3);
    t1.send_message(100);

    t1.disconnect_pipe(&r1);
    t1.disconnect_pipe(&r2);
    t1.send_message(100);

    return 0;
}

 步骤九:

        为了增进程序的通用性,使用模板对上述程序进行重新整理,如下:

#include <iostream>
#include <vector>
using namespace std;

template <typename T>
class Receiver
{
public:
    void (*fun)(T);//函数指针
    Receiver(void (*pfun)(T))
    {
        this->fun=pfun;//函数指针初始化
    }
};

template <typename T>
void slot_show(T num)
{
    cout<<"I am a slot_show function!"<<endl;
    cout<<"num:"<<num<<endl;
}

template <typename T>
void slot_print(T num)
{
    cout<<"I am a slot_print function!"<<endl;
    cout<<"num:"<<num<<endl;
}

template <typename T>
class Transimiter
{
private://成员变量改为私有属性
    vector <Receiver<T>*>receiver_v;
public:
    void send_message(T num)
    {
        for(typename vector <Receiver<T>*>::iterator it=receiver_v.begin();it!=receiver_v.end();it++)//遍历器
        {
            (*it)->fun(num);//(*it)为实际的元素值
        }

    }
    void connect_pipe(Receiver<T> *pR)//建立管道连接
    {
      this->receiver_v.push_back(pR);
    }
    void disconnect_pipe(Receiver<T> *pR)
    {
       for(typename vector <Receiver<T>*>::iterator it=receiver_v.begin();it!=receiver_v.end();it++)//遍历器
        {
            if((*it)==pR)
            {
                this->receiver_v.erase(it);
            }
        }
    }
};



int main()
{
    Transimiter <int> t1;
    Receiver <int>r1(&slot_show<int>);//定义两个不同的接收者对象
    Receiver <int>r2(&slot_print<int>);
    t1.connect_pipe(&r1);
    t1.connect_pipe(&r2);
    t1.send_message(100);

    Transimiter <float> t3;
    Receiver <float>r3(&slot_show<float>);//定义两个不同的接收者对象
    Receiver <float>r4(&slot_print<float>);
    t3.connect_pipe(&r3);
    t3.connect_pipe(&r4);
    t3.send_message(100);

    return 0;
}

       

  • 10
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值