C++成员函数指针实现简单的信号槽
#include <QDebug>
class ppp
{
public:
QString a;
void printA(void)
{
qDebug()<<a;
}
void printB(QString b)
{
qDebug()<<a<<b;
}
};
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
void (ppp::*func)();
void (ppp::*funcB)(QString);
/* func实际上是成员函数printA在类ppp中的偏移地址,
* funcB是printB的偏移地址,最终要根据实例对象加
* 上基准地址*/
func = &ppp::printA;
funcB = &ppp::printB;
ppp t1;t1.a = "t1";
ppp t2;t2.a = "t2";
/* 这里的t1.*func必须用括号括起来:(t1.*func),
* 另外这里函数指针需要对象来引用,因为func只是
* 偏移地址*/
(t1.*func)(); // 输出:"t1"
(t2.*func)(); // 输出:"t2"
(t1.*funcB)("printB");// 输出:"t1" "printB"
(t2.*funcB)("printB");// 输出:"t2" "printB"
}
现在利用回调函数的方式实现一个类似于Qt信号槽的功能,先利用模板函数兼容不同类:
#include <QHash>
template<class T>
void *recallMap()
{
typedef void (T::*Func)();
static QHash<QString, Func> hash;
return &hash;
}
template<class T>
void attach(QString mask, void (T::*func)())
{
typedef void (T::*Func)();
QHash<QString, Func> *hashP = static_cast<QHash<QString, Func> *>(recallMap<T>());
if (hashP != NULL)
{
hashP->insert(mask, func);
}
}
template<class T>
void recall(T *t, QString mask)
{
typedef void (T::*Func)();
QHash<QString, Func> *hashP = static_cast<QHash<QString, Func> *>(recallMap<T>());
if (t != NULL && hashP != NULL && hashP->contains(mask))
{
(t->*(hashP->value(mask)))();
}
}
下面是链接和调用的代码:
ppp t1;t1.a = "t1";
ppp t2;t2.a = "t2";
attach("printA", &ppp::printA);
attach("printC", &ppp::printC);
recall(&t1, "printC");
recall(&t2, "printC");
这样就可以将字符串跟函数直接关联起来,一般字符串是信号或事件,函数作为对信号或事件的响应。