自己用纯C++实现简单的QT中信号与槽机制

  • Post author:
  • Post category:其他


前天在我很久以前的一篇博文



http://blog.csdn.net/liukang325/article/details/45742675



中有人回复说看到我的博文很激动,希望我详细介绍一下信号与槽的机制,想自己通过回调实现一下。我写的博客能帮助到你我也很激动!~所以就依我自己的理解简单实现一下供你参考~

只是一个最简单的信号。并没有实现 QT中信号还带参数传递的功能。想要更深入的理解,可以阅读一下QT的源码。

大家知道想要用Qt中的信号槽。离不开QObject,那么我就写个最简单的KObject

KObject.h

#include <map>
# define kslots
# define ksignals public
# define kemit

class KObject;
struct MetaObject
{
    static void active(KObject * sender, int idx);
};
struct Connection
{
    KObject * receiver;
    int sltID;
};
typedef std::map<int, Connection> ConnectionMap;
class KObject
{
    friend class MetaObject;
    static MetaObject meta;

public:
    KObject();
    virtual ~KObject();
    static void kconnect(KObject*, int, KObject*, int);

protected:
    virtual void metacall(int sltID) = 0;
ksignals:
    //void sigtest();
public kslots:
    //void slottest();
private:
     ConnectionMap connections;
};

KObject.cpp

#include "KObject.h"

void MetaObject::active(KObject* sender, int sigID)
{
    Connection c = sender->connections[sigID];
    c.receiver->metacall(c.sltID);
}

KObject::KObject(){}

KObject::~KObject(){}

void KObject::kconnect(KObject* sender, int sigID, KObject* receiver, int sltID)
{
    Connection c = {receiver, sltID};
    sender->connections.insert(std::pair<int, Connection>(sigID, c));
}

接下来写两个测试的类,继承于KObject

TestClassA.h

#include "KObject.h"
class TestClassA : public KObject
{
public:
    TestClassA();

protected:
    void metacall(int sltID);

ksignals:
    typedef enum{
        SIG_HELLOWORLD,
    }SIG_ID;

    void sigTestA(int sigID);
};

TestClassA.cpp

#include "TestClassA.h"
TestClassA::TestClassA()
{
}

void TestClassA::metacall(int sltID)
{
}

void TestClassA::sigTestA(int sigID)
{
    MetaObject::active(this, sigID);
}

TestClassB.h

#include "KObject.h"

class TestClassB : public KObject
{
public:
    TestClassB();

    void metacall(int sltID);

public kslots:

    typedef enum{
        SLT_HELLOWORLD = 2,
    }SLT_ID;

    void slotTestB();
};

TestClassB.cpp

#include "TestClassB.h"

TestClassB::TestClassB()
{
}

void TestClassB::metacall(int sltID)
{
    switch (sltID) {
       case SLT_HELLOWORLD:
           slotTestB();
           break;
       default:
           break;
    };
}

void TestClassB::slotTestB()
{
    QDBG << "hello world TestB";
}

最后写main函数

    TestClassA a;
    TestClassB b;
    KObject::kconnect(&a, TestClassA::SIG_HELLOWORLD, &b, TestClassB::SLT_HELLOWORLD);
    a.sigTestA(TestClassA::SIG_HELLOWORLD);

调用的是a.sigTestA(TestClassA::SIG_HELLOWORLD);

会打印TestClassB::slotTestB()中的”hello world TestB”;


以上三个类所有的代码不过百来行,实现的是最基本最简单的一个类信号触发另一个类的槽函数。这里信号只是一个ID,没有像QT中那样丰富的实现信号函数,还带有多种参数传递,以及多种connect的写法。

这个例子只是方便你很简单的理解两个类之间信号与槽是怎么传递的。

希望对你有帮助~

转载请注明来源:

http://blog.csdn.net/liukang325/article/details/78151601



版权声明:本文为liukang325原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。