C++的RTTI机制功能有限
Qt提供了元对象系统,使用该系统的基类QObject所创建和派生的类,可以再运行期获取该对象的类名、父
类名,成员变量信息,成员函数信息,进而实现信号槽机制。
C++ 模拟
类定义文件 object.h
1. #ifndef DB_OBJECT
2. #define DB_OBJECT
3. #include <map>
4. # define db_slots
5. # define db_signals protected
6. # define db_emit
7. class Object;
8. struct MetaObject
9. {
10. const char * sig_names;
11. const char * slts_names;
12. static void active(Object * sender, int idx);
13. };
14. struct Connection
15. {
16. Object * receiver;
17. int method;
18. };
19. typedef std::multimap<int, Connection> ConnectionMap;
20. typedef std::multimap<int, Connection>::iterator ConnectionMapIt;
21. class Object
22. {
23. static MetaObject meta;
24. void metacall(int idx);
25. public:
26. Object();
27. virtual ~Object();
28. static void db_connect(Object*, const char*, Object*, const char*);
29. void testSignal();
30. db_signals:
31. void sig1();
32. public db_slots:
33. void slot1();
34. friend class MetaObject;
35. private:
36. ConnectionMap connections;
37. };
38. #endif
类实现文件 object.cpp
1. #include <stdio.h>
2. #include <string.h>
3. #include "object.h"
4. Object::Object()
5. {
6. }
7. Object::~Object()
8. {
9. }
10. static int find_string(const char * str, const char * substr)
11. {
12. if (strlen(str) < strlen(substr))
13. return -1;
14. int idx = 0;
15. int len = strlen(substr);
16. bool start = true;
17. const char * pos = str;
18. while (*pos) {
19. if (start && !strncmp(pos, substr, len) && pos[len]=='/n')
20. return idx;
21. start = false;
22. if (*pos == '/n') {
23. idx++;
24. start = true;
25. }
26. pos++;
27. }
28. return -1;
29. }
30. void Object::db_connect(Object* sender, const char* sig, Object* receiver, const char* slt)
31. {
32. int sig_idx = find_string(sender->meta.sig_names, sig);
33. int slt_idx = find_string(receiver->meta.slts_names, slt);
34. if (sig_idx == -1 || slt_idx == -1) {
35. perror("signal or slot not found!");
36. } else {
37. Connection c = {receiver, slt_idx};
38. sender->connections.insert(std::pair<int, Connection>(sig_idx, c));
39. }
40. }
41. void Object::slot1()
42. {
43. printf("hello dbzhang800!");
44. }
45. void MetaObject::active(Object* sender, int idx)
46. {
47. ConnectionMapIt it;
48. std::pair<ConnectionMapIt, ConnectionMapIt> ret;
49. ret = sender->connections.equal_range(idx);
50. for (it=ret.first; it!=ret.second; ++it) {
51. Connection c = (*it).second;
52. c.receiver->metacall(c.method);
53. }
54. }
55. void Object::testSignal()
56. {
57. db_emit sig1();
58. }
自己的预处理需要生成这样一个文件 db_object.cpp
1. #include "object.h"
2. static const char sig_names[] = "sig1/n";
3. static const char slts_names[] = "slot1/n";
4. MetaObject Object::meta = {sig_names, slts_names};
5. void Object::sig1()
6. {
7. MetaObject::active(this, 0);
8. }
9. void Object::metacall(int idx)
10. {
11. switch (idx) {
12. case 0:
13. slot1();
14. break;
15. default:
16. break;
17. };
18. }