参考文章:https://blog.csdn.net/perfectguyipeng/article/details/78082360
原理基础介绍
Qt中通过object类定义了connect函数,在connect函数中实现了将信号与槽函数的对应关系
这种对应关系记录在元对象类中,信号函数的定义由元对象处理器定义,在这一步可以确定信号触发时,槽函数被调用的过程。
主要理解一下几个函数:
static void db_connect(Object*, const char*, Object*, const char*);
void MetaObject::active(Object* sender, int idx)
#ifndef DB_OBJECT
#define DB_OBJECT
#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 //object类
{
static MetaObject meta;
void metacall(int idx);
public:
Object();
virtual ~Object();
static void db_connect(Object*, const char*, Object*, const char*);
void testSignal();
db_signals:
void sig1();
public db_slots:
void slot1();
friend class MetaObject;
private:
ConnectionMap connections;
};
#endif
#include "object.h"
#include <stdio.h>
#include <string.h>
Object::Object()
{
}
Object::~Object()
{
}
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] == '\0'))
{
return idx;
}
start = false;
if (*pos == '\0') {
idx++;
start = true;
}
pos++;
}
return -1;
}
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()
{
printf("hello dbzhang800!");
}
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);
}
}
void Object::testSignal()
{
db_emit sig1();
}
#include "object.h"
static const char sig_names[] = "sig1";
static const char slts_names[] = "slot1";
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;
};
}
#include "object.h"
int main()
{
Object obj1, obj2;
Object::db_connect(&obj1, "sig1", &obj2, "slot1");
obj1.testSignal();
return 0;;
}