Qt中如何根据类名来实例化对象
对于Qt 来说,是可以做到运行时,根据对象的类名字(字符串)来获得对象的实例的,这点和一些语言的反射机制是一样的。
但是在Qt中,我们需要所额外的一步,就是注册。
只要做到了注册,我们就可以 自由的创建对象了。
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
|
#include <QtCore>class Parser {public: virtual void parse() = 0; virtual ~Parser() {}};class Parser1 : public Parser {public: Parser1() { qDebug() <<"Parser1::Parser1()"; } void parse() { qDebug() << "Parser1::parse()"; } ~Parser1() { qDebug() <<"Parser1::~Parser1()"; }};Q_DECLARE_METATYPE(Parser1)class Parser2 : public Parser {public: Parser2() { qDebug() <<"Parser2::Parser2()"; } void parse() { qDebug() << "Parser2::parse()"; } ~Parser2() { qDebug() <<"Parser2::~Parser2()"; }};Q_DECLARE_METATYPE(Parser2)void factory( const char* parserName ) { int id = QMetaType::type( parserName ); if (id == -1) return; // ERROR HERE Parser *parser = static_cast<Parser*>(QMetaType::construct(id)); parser->parse(); delete parser;}int main () { qRegisterMetaType<Parser1>("Parser1"); qRegisterMetaType<Parser2>("Parser2"); qDebug() << "###### Trying create Parser1"; factory("Parser1"); qDebug() << "###### Trying create Parser2"; factory("Parser2");} |
注册分为两步,定义的时候 使用 Q_DECLARE_METATYPE 宏。
使用的时候使用 qRegisterMetaType 函数
这样就可以在Qt 中动态地创建自己定义的类了。
但是这个方法,在注册 已有的 QWidget 和 QObject 的子类的时候会遇到问题。
原因是,在创建对象的时候,Qt 中有一个函数 qMetaTypeConstructHelper 会被调用,这个函数调用了欲创建类的复制构造函数,而复制构造函数 在 QWidget 和 QObject 的子类里是被禁用的。
解决的办法 就有两个,
一,启用 复制构造函数,
二,特化重写 qMetaTypeConstructHelper 函数。
复制构造函数 的启用 需要重新派生一个子类,就不多说了。
对于第二个方法,我们只要对于每一个特定的类 单独写一个函数就好了。如果使用宏,就会大大便捷这个过程。
代码如下。
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
|
#include <QtCore>#define Q_DECLARE_QTBUILTIN_METATYPE(TYPE) \template <> \void *qMetaTypeConstructHelper(const TYPE *t) { \ Q_UNUSED(t) \ return new TYPE(); \} \Q_DECLARE_METATYPE(TYPE)Q_DECLARE_QTBUILTIN_METATYPE(QSettings)Q_DECLARE_QTBUILTIN_METATYPE(QTimer)void outputObject(const char* parseName) { QObject* obj = static_cast<QObject*>(QMetaType::construct(QMetaType::type(parseName))); qDebug() << obj; delete obj;}int main(int argc, char *argv[]){ qRegisterMetaType<QTimer>("QTimer"); qRegisterMetaType<QSettings>("QSettings"); outputObject("QTimer"); outputObject("QSettings"); QTimer* tmr = static_cast<QTimer*>(QMetaType::construct(QMetaType::type("QTimer"))); tmr->setInterval(50000); qDebug() << tmr->interval(); delete tmr; return 0;} |
转自:http://bbs.csdn.net/topics/390480286/
使用反射时同时要参考:http://www.cnblogs.com/liushui-sky/p/6422643.html
http://www.cnblogs.com/liushui-sky/p/5731477.html
浙公网安备 33010602011771号