C 實現反射 根據類名動態建立物件

2021-08-28 05:38:47 字數 3054 閱讀 9451

和網上大多數實現一樣,這裡也是採用工廠方法來實現物件的動態建立。大致原理為,建立乙個單例工廠類,其中維護乙個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...