C++實現類似java反射的功能


用過java的開發者都知道,java有一種叫做反射的功能,可以根據類名來生成類的實例,這種機制的好處就是可以在不修改代碼的情況下,可以通過配制文件來決定生成什么類的對像。那么對於使用C++開的人來說,有沒有一種方式實現類似的功能呢?

雖然C++沒有從語言層面提供反射的機制,但是還是可以簡單的模擬出類似的功能的。在查找了很多資料,也看過很多人寫的不同實現后,將其中一種我認為模擬的比較好的方案做個總結。

首先定義一個ClassInfo類:

typedef Resource* (*ResourceConstructorFn)(void);

class ClassInfo
{
public:
    ClassInfo(int type, ResourceConstructorFn creator):m_creator(creator)
    {
        Resource::regist(this);
    }
    
    Resource* create_resource()
    {
        return m_creator ? (*m_creator)() : 0;
    }
    
    ResourceConstructorFn m_creator;
};


Resource類便是我們需要反射創建的類的基類了。定義如下:

class Resource
{
public:
    Resource();
    virtual ~Resource() = 0;
    static Resource* get_resource(string name)
  {

if(m_map_resource.find(name) != m_map_resource.end())
{
  Resource* res = m_map_resource[name]->create_resource();
  return res;
}
else
{
  return NULL;
}

  }
static void regist(ClassInfo* ci)
    {
        if(ci)
        {
            if(m_map_resource.find(ci->m_type) == m_map_resource.end())
            {
                m_map_resource[ci->m_type] = ci;
            }
        }
    }
    protected:
    static std::map<string, ClassInfo*> m_map_resource; //資源類型與其類信息map,用於創建資源子類
};

ClassInfo類的構造函數里會將自身注冊到Resource基類當中,然后Resource類的get_resource(string name)函數就可以根據注冊的信息創建對應的Resource子類了。因此,我們只需讓所有Resource子類都有一個ClassInfo對像就行了。於是添加以下宏來實現:

//用於創建資源,所有繼承Resource類的子類,其定義結尾應當加此宏。
#define DECLARE_RESOURCE(class_name) \
private:\
    static ClassInfo ci; \
public:\
    ClassInfo* get_class_info(){return &ci;}\
    static Resource* create_resource(){return new class_name();}

//綁定資源及其類型,用於創建資源,所有繼承Resource類的子類,其實現中應當加此宏。    
#define BIND_RESOURCE_TYPE(class_name, name) \
ClassInfo name::ci(name, (ResourceConstructorFn)&class_name::create_resource);

class A:Resouce
{
 DECLARE_RESOURCE(A) 
};
BIND_RESOURCE_TYPE(A, "A")

只要在擴展每個Resource的子類的時候,都加入DECLARE_RESOURCEBIND_RESOURCE_TYPE這兩個宏,由於靜態變量會在程序執行最開始就初始化,也就是A類的ci成員會在一開始就將create_resource()函數注冊到Resource基類的m_map_resource中,

所以,要得到A類的實例,變只需要根據類名調用Resource::get_resource("A")即可。

雖然實現邏輯有點復雜,還需要在定義子類時加入兩個宏,但是還是可以模擬一下反射的功能的。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM