1. 程式人生 > >C++實現反射(三)

C++實現反射(三)

上一篇我們用一個 Object 類,讓所有需要反射的類都繼承這個物件,這樣雖然解決了問題,但是用起來不太方便。Object 類的存在主要為了解決儲存和返回時的型別問題,如果取消這個類,我們怎麼對這些反射類做統一處理呢?答案當然是模板。

  1. 實現一個模板類管理類名和類建構函式的對映關係,並提供構造物件的介面,每個基類需要初始化一個這樣的管理物件。
  2. 提供一個對應的 static 模板函式,用來儲存和返回對應的管理物件。
  3. 使用模板函式和 new 操作符作為每個類的建構函式。
  4. 實現一個簡單的 helper 模板類提供作為註冊的簡單封裝,並封裝巨集實現註冊。
  5. 封裝一個巨集實現反射類的建立。
#ifndef __BASE_H__
#define __BASE_H__
#include <string>
#include <map>
#include <iostream>

// 使用模板,每個基類單獨生成一個 ClassRegister
// 好處是需要反射的類不需要去繼承 Object 物件
// ClassRegister 用來管理類名->類建構函式的對映,對外提供根據類名構造物件對函式
template<typename ClassName>
class ClassRegister {
  public:
    typedef
ClassName* (*Constructor)(void); private: typedef std::map<std::string, Constructor> ClassMap; ClassMap constructor_map_; public: // 新增新類的建構函式 void AddConstructor(const std::string class_name, Constructor constructor) { typename ClassMap::iterator it = constructor_map_.find(class_name); if
(it != constructor_map_.end()) { std::cout << "error!"; return; } constructor_map_[class_name] = constructor; } // 根據類名構造物件 ClassName* CreateObject(const std::string class_name) const { typename ClassMap::const_iterator it = constructor_map_.find(class_name); if (it == constructor_map_.end()) { return nullptr; } return (*(it->second))(); } }; // 用來儲存每個基類的 ClassRegister static 物件,用於全域性呼叫 template <typename ClassName> ClassRegister<ClassName>& GetRegister() { static ClassRegister<ClassName> class_register; return class_register; } // 每個類的建構函式,返回對應的base指標 template <typename BaseClassName, typename SubClassName> BaseClassName* NewObject() { return new SubClassName(); } // 為每個類反射提供一個 helper,構造時就完成反射函式對註冊 template<typename BaseClassName> class ClassRegisterHelper { public: ClassRegisterHelper( const std::string sub_class_name, typename ClassRegister<BaseClassName>::Constructor constructor) { GetRegister<BaseClassName>().AddConstructor(sub_class_name, constructor); } ~ClassRegisterHelper(){} }; // 提供反射類的註冊巨集,使用時僅提供基類類名和派生類類名 #define RegisterClass(base_class_name, sub_class_name) \ static ClassRegisterHelper<base_class_name> \ sub_class_name##_register_helper( \ #sub_class_name, NewObject<base_class_name, sub_class_name>); // 建立物件的巨集 #define CreateObject(base_class_name, sub_class_name_as_string) \ GetRegister<base_class_name>().CreateObject(sub_class_name_as_string) #endif

下面是使用的示例:

#include <iostream>
#include <memory>
#include <cstring>
#include "base3.h"
using namespace std;

class base
{
  public:
    base() {}
    virtual void test() { std::cout << "I'm base!" << std::endl; }
    virtual ~base() {}
};

class A : public base
{
  public:
    A() { cout << " A constructor!" << endl; }
    virtual void test() { std::cout << "I'm A!" <<std::endl; }
    ~A() { cout << " A destructor!" <<endl; }
};

// 註冊反射類 A
RegisterClass(base, A);

class B : public base
{
  public :
    B() { cout << " B constructor!" << endl; }
    virtual void test() { std::cout << "I'm B!"; }
    ~B() { cout << " B destructor!" <<endl; }
};

// 註冊反射類 B
RegisterClass(base, B);

class base2
{
  public:
    base2() {}
    virtual void test() { std::cout << "I'm base2!" << std::endl; }
    virtual ~base2() {}
};

class C : public base2
{
    public :
    C() { cout << " C constructor!" << endl; }
    virtual void test() { std::cout << "I'm C!" << std::endl; }
    ~C(){ cout << " C destructor!" << endl; }
};

// 註冊反射類 C
RegisterClass(base2, C);


int main()
{
  // 建立的時候提供基類和反射類的字串類名
  base* p1 = CreateObject(base, "A");
  p1->test();
  delete p1;
  p1 = CreateObject(base, "B");
  p1->test();
  delete p1;
  base2* p2 = CreateObject(base2, "C");
  p2->test();
  delete p2;
  return 0;
}