1. 程式人生 > >C++ Reflection 的簡單實現 (反射)

C++ Reflection 的簡單實現 (反射)

之前被一些指令碼語言慣懷了,重新寫C++程式碼居然有點不適應。最明顯的是C++沒有語言層面的反射機制。回想QT是有反射的,但人家是牛X到自己實現了一個moc層,從根本上解決了這個問題。而我只是想實現一個輕量化的解決方案,最好能馬上上手用,最好是類似修飾類一樣的東西,可以和現有程式碼相容。網上搜了下,發現沒有一個我喜歡的方案。但是受他們的啟發,自己實現了一個。
思路是這樣滴,我想要這樣敲程式碼ReflectionClass *ptr = ObjectFactory::createObject("ReflectionClass"); ObjectFactory怎麼知道如何建立ReflectionClass呢?自然是需要給ObjectFactory一個註冊函式,我可以定義一個全域性的hash容器,來裝每個類對應的建立函式。每個類在定義好之後,自己把自己的建立函式註冊進去。這樣就萬事大吉啦。
進一步想到,一般需要在main函式執行之前,把所有類註冊完畢。我定義一個小的註冊類模板,在它的建構函式裡進行註冊,每個類定義好之後,再定義一個相應的全域性變數,這樣註冊函式就能先於main函式運行了。
最後,把這些過程寫成巨集,呼叫的時候就能一句話完成上述全部的工作。
說的太複雜了,還是直接看程式碼簡單一些。
#ifndef _REFLECTION_
#define _REFLECTION_

// this file realize a simple reflection mechanism
// usage :
// 1 use the macro to Register the class REG_REFLECTION_CLASS(ClassName).
// 2 then you can create the instance like that
//   ClassName *instance = (ClassName*) ObjectFactory::createObject("ClassName");           
// example :
//  REG_REFLECTION_CLASS(int);
//  int *i = (int*) ObjectFactory::createObject("int");

#include <stdlib.h>
#include <tr1/unordered_map>

typedef void* (*FactoryCreate_PTR) ();

std::tr1::unordered_map<std::string,FactoryCreate_PTR> g_creator_map;

template <class T>
class RegisterReflectionClass {
  public:
    RegisterReflectionClass (std::string name,FactoryCreate_PTR ptr)
    {
    std::tr1::unordered_map<std::string,FactoryCreate_PTR>::const_iterator it = g_creator_map.find(name);
    if(it == g_creator_map.end()){
        g_creator_map[name] = ptr;
    }else{
        std::cout << "exit error : Class \"" << name << "\" has been registered before" << std::endl;
        exit (EXIT_FAILURE);
    }
    }
};

class ObjectFactory{
  public:
    static void* createObject(std::string name)
    {
    void* obj;
    std::tr1::unordered_map<std::string,FactoryCreate_PTR>::const_iterator it = g_creator_map.find(name);
    if(it != g_creator_map.end()){
        obj = (it->second)();
        return obj;
    }
    }
};

#define REFLECTION_CLASS_CREATOR(class_name)    \
    void* class_name##_creator()        \
    {                        \
    class_name *tmp = new class_name();    \
    return (void*)tmp;            \
    }                        \

#define REG_REFLECTION_CLASS(class_name)                \
    REFLECTION_CLASS_CREATOR(class_name)                \
    RegisterReflectionClass<class_name> Reg##class_name(#class_name,class_name##_creator); \

#endif
使用 REG_REFLECTION_CLASS註冊需要反射的類
<span style="font-family: Arial, Helvetica, sans-serif; background-color: rgb(255, 255, 255);">sample程式碼:</span>
#include <iostream>
#include <string>

#include "reflection.hpp"

using namespace std;

class TestClass
{
  public:
    TestClass(string s1="",string s2="", string s3="")
    {
	p1 = s1;
	p2 = s2;
	p3 = s3;
    }

    void init(string s1="",string s2="", string s3="")
    {
	p1 = s1;
	p2 = s2;
	p3 = s3;
    }
    
    void print()
    {
	cout << p1 << " " << endl;
	cout << p2 << " " << endl;
	cout << p3 << " " << endl;
    }
  private:
    string p1,p2,p3;
};

REG_REFLECTION_CLASS(TestClass);
REG_REFLECTION_CLASS(int);

int main()
{
    int *i = (int*) ObjectFactory::createObject("int");
    cout << *i << endl;

    TestClass *test = (TestClass*) ObjectFactory::createObject("TestClass");
    test->init("str1","str2","str3");
    test->print();
    
    return 0;
}