C++實現反射(三)
阿新 • • 發佈:2018-11-01
上一篇我們用一個 Object 類,讓所有需要反射的類都繼承這個物件,這樣雖然解決了問題,但是用起來不太方便。Object 類的存在主要為了解決儲存和返回時的型別問題,如果取消這個類,我們怎麼對這些反射類做統一處理呢?答案當然是模板。
- 實現一個模板類管理類名和類建構函式的對映關係,並提供構造物件的介面,每個基類需要初始化一個這樣的管理物件。
- 提供一個對應的 static 模板函式,用來儲存和返回對應的管理物件。
- 使用模板函式和 new 操作符作為每個類的建構函式。
- 實現一個簡單的 helper 模板類提供作為註冊的簡單封裝,並封裝巨集實現註冊。
- 封裝一個巨集實現反射類的建立。
#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;
}