此篇文章借鉴他人供大家学习使用,非原创,在此向原著致谢。
转载自Qt信号与槽实现原理
object.h
#ifndef OBJECT_H
#define OBJECT_H
#include <map>
# define db_slots
# define db_signals protected
#define db_emit
class Object;
struct MetaObject
{
const char * sig_names;
const char * slts_names;
static void active(Object * sender, int idx);
};
struct Connection
{
Object * receiver;
int method;
};
typedef std::multimap<int, Connection> ConnectionMap;
typedef std::multimap<int, Connection>::iterator ConnectionMapIt;
class Object
{
public:
Object();
virtual ~Object();
void testSignal();
static void db_connect(Object*, const char*, Object*, const char*);
void metacall(int idx);
db_signals:
void sig1();
public db_slots:
void slot1();
static MetaObject meta;
friend class MetaObject;
private:
ConnectionMap connections;
};
#endif // OBJECT_H
object.cpp
#include "object.h"
#include <iostream>
#include <QString>
#include <QDebug>
//void getNext(const char *p,int *next)
//{
// int j,k;
// next[0]=-1;
// j=0;
// k=-1;
// while(j<strlen(p)-1)
// {
// if(k==-1||p[j]==p[k]) //匹配的情况下,p[j]==p[k]
// {
// j++;
// k++;
// next[j]=k;
// }
// else //p[j]!=p[k]
// k=next[k];
// }
//}
//int find_string(const char *s,const char *p)
//{
// int next[100];
// int i,j;
// i=0;
// j=0;
// getNext(p,next);
// while(i<strlen(s))
// {
// if(j==-1||s[i]==p[j])
// {
// i++;
// j++;
// }
// else
// {
// j=next[j]; //消除了指针i的回溯
// }
// if(j==strlen(p))
// return i-strlen(p);
// }
// return -1;
//}
static int find_string(const char * str, const char * substr)
{
if (strlen(str) < strlen(substr))
return -1;
int idx = 0;
int len = strlen(substr);
bool start = true;
const char * pos = str;
while (*pos) {
if (start && !strncmp(pos, substr, len) && pos[len]=='\n')
return idx;
start = false;
if (*pos == '\n') {
idx++;
start = true;
}
pos++;
}
return -1;
}
Object::Object()
{
}
Object::~Object()
{
}
void Object::testSignal()
{
db_emit sig1();
}
void Object::db_connect(Object* sender, const char* sig, Object* receiver, const char* slt)
{
int sig_idx = find_string(sender->meta.sig_names, sig);
int slt_idx = find_string(receiver->meta.slts_names, slt);
if (sig_idx == -1 || slt_idx == -1) {
perror("signal or slot not found!");
} else {
Connection c = {receiver, slt_idx};
sender->connections.insert(std::pair<int, Connection>(sig_idx, c));
}
}
void Object::slot1()
{
qDebug() << "hello world!";
}
void MetaObject::active(Object* sender, int idx)
{
ConnectionMapIt it;
std::pair<ConnectionMapIt, ConnectionMapIt> ret;
ret = sender->connections.equal_range(idx);
for (it=ret.first; it!=ret.second; ++it) {
Connection c = (*it).second;
c.receiver->metacall(c.method);
}
}
db_object.cpp
#include "object.h"
static const char sig_names[] = "sig1\n";
static const char slts_names[] = "slot1\n";
MetaObject Object::meta = {sig_names, slts_names};
void Object::sig1()
{
MetaObject::active(this, 0);
}
void Object::metacall(int idx)
{
switch (idx) {
case 0:
slot1();
break;
default:
break;
};
}
main.cpp
#include <QApplication>
#include "object.h"
#include "Windows.h"
//#include <QDebug>
//#include "stdio.h"
//#include <iostream>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
Object obj1, obj2;
Object::db_connect(&obj1, "sig1", &obj2, "slot1");
obj1.testSignal();
// UINT nHash;
// nHash = (nHash << 5) + nHash + 1;
qDebug() << nHash;
printf("%d\n", nHash);
// std::cout << nHash << std::endl;
return a.exec();
}