和網上大多數實現一樣,這裡也是採用工廠方法來實現物件的動態建立。大致原理為,建立乙個單例工廠類,其中維護乙個map(類名->物件建立函式)。建立物件時,傳入類名,然後根據此類名查詢出建立函式,最後建立物件。
採用這種方式,有乙個關鍵問題,便是在工廠中註冊類名。我們的辦法是針對於每乙個類(class),定義乙個註冊類(classreg),在註冊類(classreg)的建構函式中註冊此類(class),然後再定義乙個註冊類的全域性物件,在該全域性物件初始化時,便會執行註冊**完成註冊。
看到到這裡懶人不樂意了,難道我們每寫乙個類,還要寫乙個相應的註冊類?於是有人提出了使用巨集來替換相應的**,這樣便大大減少了重複**量。
採用巨集當然可以,但是只能滿足部分懶人。還有一部分人更懶,他們連使用這個巨集完成註冊都不想幹,是呀,每寫完乙個類,還要在類後面使用巨集來註冊,這樣確實還是比較麻煩。而且這樣**不夠美觀,也不便於維護,同時採用巨集來轉換類名,遇到命名空間,巢狀類,會非常麻煩,我們必須在註冊的時候,把名字寫全,比如reg_class(mynamespace::myclass::mystruct)。
那麼有沒有更好的方法呢?當然有,我們可以用類模板來實現這種功能。設想這種方式,若我們要定義乙個類myclass,並且想讓此類支援動態建立,那麼我們只需這樣定義即可class myclass : public dynamiccreate{};。這樣是不是清晰多了?下面請看**:
dynamicfactory.h檔案
#ifndef __dynamic_factory_h__
#define __dynamic_factory_h__
#ifdef __gnuc__
#include #endif
#include #include #include #include #include #include // 動態物件基類
class dynamicobject
virtual ~dynamicobject() {}
};// 動態物件建立工廠
class dynamicfactory
// 解析型別名稱**換為 a::b::c 的形式)
static std::string readtypename(const char * name)
bool regist(const char * name, createfunction func)
std::string type_name = readtypename(name);
return _create_function_map.insert(std::make_pair(type_name, func)).second;
} dynamicobject * create(const std::string & type_name)
std::map::iterator it = _create_function_map.find(type_name);
if (it == _create_function_map.end())
return it->second();
} templatet * create(const std::string & type_name)
t * real_obj = dynamic_cast(obj);
if (!real_obj)
return real_obj;
}public:
std::map_create_function_map;
};// 動態物件建立器
templateclass dynamiccreate : public dynamicobject
struct registor
}inline void do_nothing()const
}; static registor s_registor;
public:
dynamiccreate()
virtual ~dynamiccreate() };
template typename dynamiccreate::registor dynamiccreate::s_registor;
#endif
**不多,就不做解釋了。
測試**mian.cpp
#include #include "dynamicfactory.h"
class test1 : public dynamiccreate
};namespace ok
class test3 : public dynamiccreate
};}; struct test4 : public dynamiccreate
};}using namespace ok;
//測試**
int main()
輸出:
[programmer@localhost test]$ ./test
create test1 success
create ok::test2 success
create ok::test2::test3 success
create ok::test4 success
下面給出上面省略的 readtypename函式**
// 解析型別名稱**換為 a::b::c 的形式)
// gcc 的type_info::name()輸出的名稱很猥瑣,這裡只做簡單的解析,只支援自定義的結構體(非模板),類(非模板)、列舉、聯合
static std::string readtypename(const char * name)
}return std::string(name);
#else
char * real_name = abi::__cxa_demangle(name, nullptr, nullptr, nullptr);
std::string real_name_string(real_name);
free(real_name);
return real_name_string;
#endif
}
C 利用反射根據類名建立類的例項物件
反射 其實就是利用程式集的元資料資訊。反射可以有很多方法,編寫程式時請先導入 system.reflection 命名空間。1 假設你要反射乙個 dll 中的類,並且沒有引用它 即未知的型別 assembly assembly assembly.loadfile 程式集路徑,不能是相對路徑 引導程式...
C 利用反射根據類名建立類的例項物件
1 假設你要反射乙個 dll 中的類,並且沒有引用它 即未知的型別 assembly assembly assembly.loadfile 程式集路徑,不能是相對路徑 引導程式集 exe 或 dll dynamic obj assembly.createinstance 類的完全限定名 即包括命名空...
C 根據類名建立類的例項物件
因為我使用這個方法的類都是和abstractscenepagedto處於乙個命名空間以及程式集下的,所以獲取命名空間和程式集的時候,直接使用abstractscenepagedto這個類進行獲取,這樣更準確一些,也不怕專案遷移改名。1 private t createactivityscenepag...