當前位置:
首頁 > 知識 > c++ 反射機制:用類名作變數,動態創建對象

c++ 反射機制:用類名作變數,動態創建對象

什麼是反射

創建對象的角度上來看,狹義的說,比如有個 class A ,你能直接 new A() 來創建 對象。但是如果想根據字元串 「A」 來創建 class A 的對象,比如 使用 new 「A」 的形式來創建 對象,甚至 「A」 是個變數。 str = 「A」 , new str.

這種把 class 作為變數,又能在運行時創建對象的機制,就叫做反射。

大部分的高級編程語言,先天是支持反射的。用 lua 舉例

local AllTypes = {
Type1 = 1,
Type2 = 2,
Type3 = 3,
}
local typeClsHash = {}
typeClsHash[AllTypes.Type1] = Cls1
typeClsHash[AllTypes.Type2] = Cls2
typeClsHash[AllTypes.Type3] = Cls3
local theType = AllTypes.Type2
local cls = typeClsHash[theType]
local instance = cls:new()
instance:doSth()
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16

如上面的代碼,可以動態的通過 theType 變數的值,來選擇 new 哪個 class 的對象。這樣代碼寫起來就比較靈活,省去了寫一大堆醜陋的 switch case,if/else 。

c++ 代碼示例

需求

遊戲裡面有很多UI,是 BaseMenu 的子類。包括MenuStageSelect, MenuHUD 等等。希望通過 MenuManager::pushMenu() 一個函數,寫明 Menu 的類型,動態創建和現實對應的 Menu.

原理

由於c++ 語言先天不支持反射機制,因此這種動態 new 不同 class 的實例的機制,在實現起來,必須依賴於函數指針。

用一個 std::map<>來存儲不同類型的Menu 的創建函數,key 是 menu類型,value 是創建的函數指針。

這樣才能實現反射機制,動態創建對象。

實現

MenuManager.h 定義所有 BaseMenu子類的枚舉

typedef enum
{
MENU_STAGE_SELECT,
MENU_HUD,
}MenuType;
1
2
3
4
5


MenuManager 定義一個 std::map 成員,用於存儲哪個類型的 menu ,由哪個函數來負責創建。

// Registered menus
typedef std::function<BaseMenu*()> MenuCreateFuncType;
std::map<MenuType, MenuCreateFuncType> _registerMenus;
1
2
3


每個 Menu 都需要提供自己的創建函數。在對應的類裡面,實現一個 static XXX* createInstance() 的方法。

例如 MenuHUD

在 MenuHUD.h 聲明 static MenuHUD* createInstance() 函數

class MenuHUD : public BaseMenu
{
public:
static MenuHUD* createInstance();
1
2
3
4

在 MenuHUD.cpp 里實現它

MenuHUD* MenuHUD::createInstance()
{
return new MenuHUD();
}
1
2
3
4

每個 BaseMenu 的子類都需要實現這個靜態函數。



在遊戲初始化時,註冊所有 Menu 的創建函數。

void MenuManager::registAllMenus()
{
_registerMenus[MenuType::MENU_STAGE_SELECT] = MenuStageSelect::createInstance;
_registerMenus[MenuType::MENU_HUD] = MenuHUD::createInstance;
}
1
2
3
4
5


這些準備工作做完之後,就可以在 MenuManager::pushMenu(MenuType menuType) 函數里,根據 Menu 類型,動態 new 出不同類型的 menu 的實例了。

void MenuManager::pushMenu(MenuType menuType)
{
BaseMenu* pInstance = _registerMenus[menuType]();
/*
Do other things...
*/
}
1
2
3
4
5
6
7


上面 map 的 key 是 Menu 的枚舉。如果希望用 Menu 的類名做變數,只需要把 key 的 枚舉,修改為 std::string ,在 registerAllMenus() 裡面,用類名作 key 即可。

c++ 反射機制:用類名作變數,動態創建對象

喜歡這篇文章嗎?立刻分享出去讓更多人知道吧!

本站內容充實豐富,博大精深,小編精選每日熱門資訊,隨時更新,點擊「搶先收到最新資訊」瀏覽吧!


請您繼續閱讀更多來自 程序員小新人學習 的精彩文章:

Monkey可視化工具開發
springboot之定時任務

TAG:程序員小新人學習 |