C++ 九陰真經之動態創建

動態創建對很多人來說,都不陌生,在一些大型項目中是比較常見的,也是MFC的核心機制,隨着C++新標準的演化,很多東西都可以很簡單的就實現。

實現代碼:

#include <vector>
#include <functional>
#include "noncopyable.h"
#include "singleton.h"
#include "anyval.h"


#define PRIVATE_REG_DYNCREATE_4(class_name, baseName1, baseName2, baseName3) 
class class_name##Register { 
private: 
    static ClassRegistor<class_name> reg_; 
}; 
ClassRegistor<class_name> class_name##Register::reg_(#class_name, #baseName1, #baseName2, #baseName3)

#define PRIVATE_REG_DYNCREATE_3(class_name, baseName1, baseName2) 
class class_name##Register { 
private: 
    static ClassRegistor<class_name> reg_; 
}; 
ClassRegistor<class_name> class_name##Register::reg_(#class_name, #baseName1, #baseName2)

#define PRIVATE_REG_DYNCREATE_2(class_name, baseName) 
class class_name##Register { 
private: 
    static ClassRegistor<class_name> reg_; 
}; 
ClassRegistor<class_name> class_name##Register::reg_(#class_name, #baseName)


#define PRIVATE_REG_DYNCREATE_1(class_name) PRIVATE_REG_DYNCREATE_2(class_name, class_name)


#define PRIVATE_MACRO_VAR_ARGS_IMPL_COUNT(_1,_2,_3,_4,_5,_6,_7,_8,_9, N, ...) N
#define PRIVATE_MACRO_VAR_ARGS_IMPL(args)  PRIVATE_MACRO_VAR_ARGS_IMPL_COUNT args
#define COUNT_MACRO_VAR_ARGS(...)  PRIVATE_MACRO_VAR_ARGS_IMPL((__VA_ARGS__,10,9,8,7,6,5 4,3,2,1,0))

#define PRIVATE_MACRO_CHOOSE_HELPER2(M, count)  M##count
#define PRIVATE_MACRO_CHOOSE_HELPER1(M, count)  PRIVATE_MACRO_CHOOSE_HELPER2(M, count)
#define PRIVATE_MACRO_CHOOSE_HELPER(M, count)   PRIVATE_MACRO_CHOOSE_HELPER1(M, count)

//實現宏不定參數的重載
#ifdef WIN32
//EXPAND 用於解決windows上編譯器將__VA_ARGS__展開成一個參數的問題
#define EXPAND(...) __VA_ARGS__
#define REG_DYNCREATE(...) EXPAND(PRIVATE_MACRO_CHOOSE_HELPER(PRIVATE_REG_DYNCREATE_, COUNT_MACRO_VAR_ARGS( __VA_ARGS__))( __VA_ARGS__))
#else
#define REG_DYNCREATE(...) PRIVATE_MACRO_CHOOSE_HELPER(PRIVATE_REG_DYNCREATE_, COUNT_MACRO_VAR_ARGS( __VA_ARGS__))( __VA_ARGS__)
#endif	
#define DYN_CREATE(objName) CObjectFactoryAgent::get_instance().CreateObject(objName) 

class CObjectFactory 
{
public:
    template<typename T>
    void RegisterObject(const char* objName)
    {
        std::function<void* ()> function = []() {
			return new T;
		};

        m_creatorMap[objName] = AnyVar(function);
    } 
    void *CreateObject(const std::string &objName)
    {
        if(m_creatorMap.find(objName) == m_creatorMap.end())
        {
            return nullptr;
        }
        AnyVar resolver = m_creatorMap[objName];
		std::function<void* ()> func = any_cast<std::function<void* ()>>(resolver);
        return func();
    }
private:
	std::map<std::string, AnyVar> m_creatorMap;
};

typedef Singleton<CObjectFactory> CObjectFactoryAgent;



//運行時類對象管理
class CRuntimeClass
{
    //運行時類對象
    struct CRuntimeNode
    {
        //類名稱
        std::string m_strClassName;
        //繼承類
        std::vector<CRuntimeNode*>  m_vecInherit;

    };
public:
    //判斷A是B的基類
    bool IsBaseOf(const std::string& baseName, const std::string& objName)
    {
        auto itFind = m_runtimeNode.find(objName);
        if(itFind == m_runtimeNode.end())
        {
            return false;
        }
        for(auto item : itFind->second.m_vecInherit)
        {
            if(item->m_strClassName == baseName)
            {
                return true;
            }
            if(IsBaseOf(baseName, item->m_strClassName))
            {
                return true;
            }
        }
        return false;
    }

    template<typename... Args >
    void RegisterInherit(const char* objName, const char* baseName, Args... args)
    {
        CRuntimeNode& node = GetRunNode(objName);
        if(std::string(objName) != baseName)
        {
            CRuntimeNode& inhNode = GetRunNode(baseName);
            node.m_vecInherit.push_back(&inhNode);
        }
        RegisterInherit(objName, args...);
    }

    void RegisterInherit(const char* objName, const char* baseName)
    {
        CRuntimeNode& node = GetRunNode(objName);
        if(std::string(objName) != baseName)
        {
            CRuntimeNode& inhNode = GetRunNode(baseName);
            node.m_vecInherit.push_back(&inhNode);
        }
    }

    CRuntimeNode& GetRunNode(const char* objName)
    {
        if(m_runtimeNode.find(objName) == m_runtimeNode.end())
        {
            m_runtimeNode[objName] = CRuntimeNode{objName, {}};
        }
        return m_runtimeNode[objName];
    }
private:
    //保持所有對象
    std::map<std::string, CRuntimeNode> m_runtimeNode;
};

typedef Singleton<CRuntimeClass> CRuntimeClassAgent;

template<typename T>
class ClassRegistor
{
public:
    template<typename... Args >
    ClassRegistor(const char* objName, Args... args)
    {
        CObjectFactoryAgent::get_instance().RegisterObject<T>(objName);
        CRuntimeClassAgent::get_instance().RegisterInherit(objName, args...);
    }
private:
	void do_nothing(ClassRegistor const &) {}
};

 

測試代碼:

class Test
{
public:
    Test()
    {
        std::cout << "Create Test" << std::endl;
    }
};
REG_DYNCREATE(Test);

class Shape
{
public:
    virtual void Draw() = 0;
    virtual ~Shape() {}
};


class Circle : public Shape
{
public:
    void Draw()
    {
        std::cout << "Circle" << std::endl;
    }
    ~Circle(){};
};
REG_DYNCREATE(Circle, Shape);

class Square : public Shape
{
public:
    void Draw()
    {
        std::cout << "Square" << std::endl;
    }
    ~Square(){};
};
REG_DYNCREATE(Square, Shape);

class Rectangle : public Shape
{
public:
     void Draw()
    {
        std::cout << "Rectangle" << std::endl;
    }
    ~Rectangle(){};
};
REG_DYNCREATE(Rectangle, Shape);


//動態創建
int main()
{
    std::cout << "開始" << std::endl;
   
    Shape *ps;
    ps = static_cast<Shape *>(DYN_CREATE("Circle"));
    ps->Draw();
    delete ps;
 
    ps = static_cast<Shape *>(DYN_CREATE("Square"));
    ps->Draw();
    delete ps;
 
    ps = static_cast<Shape *>(DYN_CREATE("Rectangle"));
    ps->Draw();
    delete ps;


    auto ptr = static_cast<Test *>(DYN_CREATE("Test"));

    if(CRuntimeClassAgent::get_instance().IsBaseOf("Shape", "Square"))
    {
        std::cout << "shape is base of Square" << std::endl;
    }
        
    return 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章