首页 > 技术文章 > c++通过类名动态创建对象

hansjorn 2016-03-03 20:17 原文

转载:http://www.seacha.com/article.php/knowledge/cbase/2013/0615/2154.html

主要思想:在每次创建类的过程中,通过各自类的辅助类(所以每个类必须包含IMPLEMENT_DYNCRT_BASE)向基类通过“注册函数'注册,然后通过重载“工厂函数”,在创建类时,自身创建类。这里函数指针的使用非常重要。

#include <map>
#include <string>

#define DECLEAR_DYNCRT_BASE(CBase) \
    public: \
        typedef CBase *(*ClassGen)(); /* 声明函数指针*/ \
        static CBase *Create(const string &class_name) /* 工厂函数 */ \
        { \
            std::map<string, ClassGen>::iterator iter = m_class_set.find(class_name); \
            if (m_class_set.end() != iter) \
            { \
                return ((*iter).second)(); \
            } \
            return NULL; \
        } \
    protected: \
        static void Register(const string &class_name, ClassGen class_gen) /* 注册函数 */ \
        { \
            m_class_set.insert(map<string, ClassGen>::value_type(class_name, class_gen)); \
        } \
        static std::map<string, ClassGen> m_class_set /* 存储子类信息 */

// 用于实现基类
#define IMPLEMENT_DYNCRT_BASE(CBase) \
    std::map<string, CBase::ClassGen> CBase::m_class_set

#define DECLEAR_DYNCRT_CLASS(CDerived, CBase) \
    public: \
        struct CDerived##Register /* 辅助类,用于注册 */ \
        { \
            CDerived##Register() \
            { \
                static bool bRegistered = false; /* 注册子类,只注册一次 */ \
                if(!bRegistered) \
                { \
                    CBase::Register(#CDerived, CDerived::Create); /* 注册子类信息 */ \
                    bRegistered = true; \
                } \
            } \
        }; \
        static CBase *Create() /* 工厂函数 */ \
        { \
            return new CDerived; \
        } \
        static struct CDerived##Register m_t##CDerived##Register


// 用于实现一个能被动态创建的类
#define IMPLEMENT_DYNCRT_CLASS(CDerived) \
    static CDerived::CDerived##Register m_t##CDerived##Register



class CBase
{
    DECLEAR_DYNCRT_BASE(CBase);
    DECLEAR_DYNCRT_CLASS(CBase, CBase);
    public:
        virtual void Print()
        {
            std::cout << "This is base!" << std::endl;
        }
};

IMPLEMENT_DYNCRT_BASE(CBase);
IMPLEMENT_DYNCRT_CLASS(CBase);


class TEST: public CBase
{
    DECLEAR_DYNCRT_CLASS(TEST, CBase);
    public:
        virtual void Print()
        {
            cout << "This is test!" << endl;
        }
};
IMPLEMENT_DYNCRT_CLASS(TEST);

int main()
{
    CBase* base = CBase::Create("TEST");
    if (base)
    {
        base->Print();
    }

    return 0;
}

 

推荐阅读