C++反射


反射机制实现C++通过字符串(类名)创建对象
因为前不久需要做一个合并多个项目代码,所以需要通过配置文件来控制创建对象,百度用字符串创建对象,搜索半天无果,后来翻看大话设计模式的时候在工厂模式看到一个反射机制,
即通过类名创建对象,所以搜索了一下,果然能够找到,所以下载以后分析了哈,进行自己需求进行修改,现整理一下。使用qt5.5.1进行编码。
一、思路分为以下几步:
1、定义一个回调函数,用来创建这个类的实例;定义一个哈希,用于保存类名和创建实例的回调函数;
2、设计一个单例,用于管理哈希。(可用静态成员变量替换);
3、设计一个工厂类,。通过类工厂来动态创建类对象和注册类;
4、创建注册类,将回调函数存入哈希里面,类名字做为map的key值;
5、定义需要创建对象的类,用于测试。

二、  下面我来一步一步的讲解具体的实现方法。
1、声明
首先声明一个回调函数
typedef void* (*fun_ptr)();
声明一个哈希:
typedef std::map<const QString, fun_ptr> create_obj_map; //用来保存回调函数指针,通过registClass()函数来实现类名和函数的插入。

2、定义单例
定义一个单例,用于处理哈希,也可以定义成一个静态成员变量,但是之前试过几次,没成功,先使用单例吧。
class LazySingleton
{
public:
    template<class T>
    static T& instance()
    {
        static T _instance;
        return _instance;
    }
};

3、定义工厂类
定义一个工厂类,用于通过此获取哈希,方法registerClass用于插入类名和创建此类的方法,getInstance函数返回哈希中通过回调函数创建的类的实例化,参数为传入的类名。
class ClassFactory
{
public:
    static void *getInstance(const QString &className);
    static void registerClass(const QString &className, fun_ptr fp);
};

void *ClassFactory::getInstance(const QString &className)
{
    std::cout << LazySingleton::instance<create_obj_map>().size() << std::endl;

    create_obj_map::iterator iter = LazySingleton::instance<create_obj_map>().begin();

    create_obj_map::iterator iterEnd = LazySingleton::instance<create_obj_map>().end();

    while (iter != iterEnd)
    {
        if (iter->first == className)
        {
            return iter->second();
        }
               iter++;
    }
    return NULL;
}


void ClassFactory::registerClass(const QString &className, fun_ptr fp)
{
      LazySingleton::instance<create_obj_map>().insert(std::make_pair(className, fp));
}

这样,我们的单例工厂类就设计完成了。

4、添加注册类
下面我们需要设计一个用来动态创建类的类,被创建的类通过本类来向类工厂注册对象的函数。
class Register
{
public:
   Register(const char* className, fun_ptr fp);
};

 
Register::Register(const char* className, fun_ptr fp)
{
    ClassFactory::registerClass(className, fp);
}


该类设计了个宏,用于实现动态创建,后面的类中会用到。

该宏主要为了实现两个功能,一个是配合类工厂来创建一个新的类,新的类用于创建传入的类,一个是将新的类的创建对象的方法注册到哈希中。


下面先帖代码:

#define REGISTER(ClassName) \
    class Register##ClassName \
    { \
    public: \
        static void* instance() \
        { \
            return new ClassName; \
        } \
    private: \
       static const Register _staticRegister; \
    }; \
    const Register Register##ClassName::_staticRegister(#ClassName, Register##ClassName::instance);

先通过宏替换,生成一个新类,并且一个静态方法,用于创建对象。
最后一行是用于调用新类的静态成员变量,通过此静态成员变量的构造函数,把类注册到哈希里
(此处感觉Register类设计有点多余,是否可以考虑直接最后一句调用ClassFactory::registerClass(className, fp);来进行类注册,后面再来考虑吧)
,参数,第一个是类名,第二个是新类的创建对象的函数。
到这一步,类反射的功能即将要实现了。
5、添加被创建的类
下面我们来设计最后一个类,就是将要被动态创建的类,先帖码。
class Foo
{
public:
    Foo()
    {
        _id = 1;
        _name = "Foo";
    }

public:
    int _id;
    std::string _name;
};

REGISTER(Foo);

 Foo类是我们要动态创建出来的类,REGISTER(Foo)用于把类foo进行宏替换后生成一个新类,用于创建foo的对象的。

 

6、测试
到此,所有的准备工作都做好了,接下来就是测试了。
在main中添加代码:
Foo* foo = static_cast<Foo*>(ClassFactory::getInstance("Foo"));
std::cout << foo->_name << std::endl;
当界面上打印输出Foo的时候,就证明是成功了。
 
7、总结
到此,C++反射的实现讲解完成,这类实现方法适合在开发各类的编辑器中去使用,包括微软的MFC等等。
在开发编辑器的阶段,并没有相应的类,但是使用者想通过在编辑器中传入类的名字,然后在开发中,根据编辑器传入的类名,新建一个类去实现的话,这种方法非常适用,更多的用法等待大家去发掘。
不足之处欢迎大家指正。

Ps:此方法参考了网友的文章,需要的可参考:
http://blog.csdn.net/cen616899547/article/details/9317323
http://blog.csdn.net/scythe666/article/details/51718864

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值