1、QT元对象说明
QT 元对象Q_OBJECT 类似MFC的类型识别,不同之处在于,类型识别使用MFC的宏定义,依赖语言, 而QT是将元对象通过MOC系统解析成中间文件,模块之间通信,可以包含相应的MOC文件,C++编译MOC,不同的MOC保存自己的QT对象信息.
2、QT信号槽使用原型
class Object
{
Q_OBJECT
public:
Object();
virtual ~Object();
signals:
void sig1();
public slots:
void slot1();
};
在实际的使用中 需要解析此文件,特别是要实现Q_OBJECT。在本模拟中我们自己手动解析成最终文件
3、QT元对象模拟实现
1、解析的类moc头文件
#ifndef DB_OBJECT
#define DB_OBJECT
#include<map>
#define db_slots
#define db_signals protected
#define db_emit
#pragma once
class QObject;
//元对象系统 负责搜集信号与槽的名称
struct MetaObject
{
//信号组
const char * sig_names;
//槽组
const char * slts_names;
//激活某个信号 ,idx信号索引
static void active(QObject * sender, int idx);
};
//被连接对象信息
struct Connection
{
QObject * receiver;
int method;
};
//保存信号索引 与连接对象映射
typedef std::multimap<int, Connection> ConnectionMap;
typedef std::multimap<int, Connection>::iterator ConnectionMapIt;
class QObject
{
static MetaObject meta;
void metacall(int idx);
public:
QObject();
//建立连接
static void db_connect(QObject*, const char*, QObject*, const char*);
//测试用
void testSignal();
db_signals:
void sig1();
public db_slots:
void slot1();
friend class MetaObject;
private:
ConnectionMap connections;
};
#endif
2、解析的类moc.CPP文件
#include "stdafx.h"
#include "QObject.h"
static const char sig_names[] = "sig1\n";
static const char slts_names[] = "slot1\n";
MetaObject QObject::meta = { sig_names, slts_names };
QObject::QObject()
{
}
void QObject::sig1()
{
MetaObject::active(this, 0);
}
void QObject::slot1()
{
printf("hello dbzhang800!");
}
//激活信号
void QObject::metacall(int idx)
{
switch (idx) {
case 0:
slot1();
break;
default:
break;
};
}
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;
}
void QObject::db_connect(QObject* sender, const char* sig, QObject* 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 QObject::testSignal()
{
db_emit sig1();
}
void MetaObject::active(QObject* 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);
}
}
3、模拟使用
// TestQobject.cpp : 定义控制台应用程序的入口点。
//模拟QT元对象系统
//参照Qt信号与槽实现原理 http://blog.csdn.net/fuyunzhishang1/article/details/48345381
#include "stdafx.h"
#include "QObject.h"
#include <iostream>
using namespace std;
//QObject 为解析后的文件,Qt的元对象系统预处理器叫做moc,我们自己手动解析了,
/* 在QT类似如下使用
class Object
{
public:
Object();
virtual ~Object();
db_signals:
void sig1();
public db_slots:
void slot1();
};
*/
# define SLOT(a) #a
# define SIGNAL(a) #a
int _tmain(int argc, _TCHAR* argv[])
{
char p[32] = SLOT(QObject);
cout << " cur_value: " << p << endl;
QObject obj1, obj2;
QObject::db_connect(&obj1, SLOT(sig1), &obj2, SIGNAL(slot1));
obj1.testSignal();
getchar();
return 0;
}
注:以上代码引用http://blog.csdn.net/fuyunzhishang1/article/details/48345381