C++ Builder 的反射 (二) - Reflection Factory

C++ Builder 參考手冊 ? C++ Builder 的反射 (二) - Reflection Factory


上一篇文章 C++ Builder 的反射 (Reflection) (一) 介紹了從 TObject 繼承的類的反射方法,這篇文章繼續(xù)論述從 TObject 繼承的類的反射,根據(jù)上一篇文章,做一個通用的類模板,這個類模板需要 C++ 11 / clang 編譯器来屠。本文的程序和例子已經(jīng)用 C++ Builder 10.2.3 版本 clang 32位 和 clang 64位編譯器測試通過。

  1. Reflection Factory 類模板
  2. 測試控件的反射
  3. 測試自己寫的類的反射

1. Reflection Factory 類模板

THsuanluReflectionFactory 類模板的參數(shù):

  • TBaseClass 為可以反射的類的公共父類,通過類名字符串反射創(chuàng)建的類通過這個類型的指針返回馍驯;
  • TConstructorParams 為反射的類的構(gòu)造函數(shù)的參數(shù)的類型阁危,這不是單一的參數(shù),而是一組隨意個數(shù)和類型的參數(shù)汰瘫,也可以沒有狂打。由于創(chuàng)建類的時候,必需調(diào)用類的構(gòu)造函數(shù)吟吝,所以需要提供類的構(gòu)造函數(shù)的每個參數(shù)的類型菱父,請參考 C++ 可變參數(shù)的模板,構(gòu)造函數(shù)參數(shù)相同的類剑逃,可以注冊到這個 Reflection Factory 里面浙宜;

Register 方法為注冊需要反射的類,模板參數(shù) TClassType 為要注冊的類蛹磺;
Create 方法為通過類名字符串創(chuàng)建類粟瞬,參數(shù) sClassName 為類名字符串,參數(shù) Params 為構(gòu)造函數(shù)的可變參數(shù)萤捆,通過 new TClassType(Params...) 創(chuàng)建注冊的類裙品。

#include <map>
template <class TBaseClass, class... TConstructorParams> // 公共父類, 構(gòu)造函數(shù)參數(shù)類型
class THsuanluReflectionFactory
{
private:
    std::map<UnicodeString, TBaseClass*(*)(TConstructorParams...)>_ClassMap;

public:
    template<class TClassType> // 要注冊的類
    void Register(void) // 注冊 TClassType 類
    {
        _ClassMap[TClassType::ClassName()] = [](TConstructorParams... Params) -> TBaseClass*
        {
            return new TClassType(Params...);
        };
    }

    TBaseClass *Create(UnicodeString sClassName, TConstructorParams... Params)
    {
        auto iter = _ClassMap.find(sClassName);
        if(iter == _ClassMap.end())
            throw Exception(L"類 \"" + sClassName + L"\" 未注冊");
        return iter->second(Params...);
    }
};

2. 測試控件的反射

  • 這個例子在程序開始運行時,即在主窗口的構(gòu)造函數(shù)里面俗或,注冊了 TLabel市怎、TButton、TMemo辛慰、TEdit区匠、TCheckBox、TRadioButton帅腌、TComboBox 等幾個控件類驰弄,可以使用他們的類名字符串來創(chuàng)建控件對象。
  • 由于控件類的構(gòu)造函數(shù)都有一個 TComponent* Owner 參數(shù)速客,在定義 ControlsFactory 的時候戚篙,模板參數(shù)除了公共父類 TControl 之外,還有一個 TComponent* 參數(shù)溺职。
THsuanluReflectionFactory<TControl, TComponent*> ControlsFactory;
//---------------------------------------------------------------------------
__fastcall TForm1::TForm1(TComponent* Owner)
    : TForm(Owner)
{
    ControlsFactory.Register<TLabel>();
    ControlsFactory.Register<TButton>();
    ControlsFactory.Register<TMemo>();
    ControlsFactory.Register<TEdit>();
    ControlsFactory.Register<TCheckBox>();
    ControlsFactory.Register<TRadioButton>();
    ControlsFactory.Register<TComboBox>();
}
//---------------------------------------------------------------------------
void __fastcall TForm1::ButtonCreateClick(TObject *Sender)
{
    try
    {
        TControl *p = ControlsFactory.Create(EditClassName->Text, this);
        p->Parent = this;
        p->SetBounds(EditLeft->Text.ToIntDef(0), EditTop->Text.ToIntDef(0), EditWidth->Text.ToIntDef(80), EditHeight->Text.ToIntDef(30));
    }
    catch(Exception &e)
    {
        ShowMessage(e.Message);
    }
}

編輯框 EditClassName 輸入控件的類名岔擂,
編輯框 EditLeft, EditTop, EditWidth, EditHeight 分別用于輸入控件的位置和大小,
按鈕 ButtonCreate 創(chuàng)建控件浪耘,ButtonCreateClick 方法就是點擊這個按鈕執(zhí)行的代碼智亮。

測試使用 Reflection Factory 控件反射 - 窗口設(shè)計

運行結(jié)果:

創(chuàng)建一個 TComboBox:

創(chuàng)建一個 TComboBox

再創(chuàng)建一個 TCheckBox 和一個 TRadioButton

再創(chuàng)建一個 TCheckBox 和一個 TRadioButton

3. 測試自己寫的類的反射

由于本文討論從 TObject 繼承的類的反射,這里寫幾個類:其中 THsuanluBase 從 TObject 繼承点待,作為其他幾個類的公共父類阔蛉,反射的結(jié)果是通過這個類型的指針返回通過類名字符串創(chuàng)建的對象。要注意:通過父類指針訪問子類的方法要定義為虛函數(shù)癞埠。

class THsuanluBase : public TObject
{
public:
    virtual void PrintMessage(void){ Form1->Memo1->Lines->Add(L"這是父類的 PrintMessage 方法"); }
};
//---------------------------------------------------------------------------
class THsuanluTest1 : public THsuanluBase
{
public:
    virtual void PrintMessage(void){ Form1->Memo1->Lines->Add(L"這是 THsuanluTest1 的 PrintMessage 方法"); }
};
//---------------------------------------------------------------------------
class THsuanluTest2 : public THsuanluBase
{
public:
    virtual void PrintMessage(void){ Form1->Memo1->Lines->Add(L"這是 THsuanluTest2 的 PrintMessage 方法"); }
};
//---------------------------------------------------------------------------
class THsuanluTest3 : public THsuanluTest2
{
public:
    virtual void PrintMessage(void){ Form1->Memo1->Lines->Add(L"這是 THsuanluTest3 的 PrintMessage 方法"); }
};
  • 定義 HsuanluFactory 時状原,由于自己寫的這些類的構(gòu)造函數(shù)沒有參數(shù)聋呢,所以模板參數(shù)只有一個公共父類 THsuanluBase
  • 在程序開始執(zhí)行的時候,即主窗口的構(gòu)造函數(shù)里面注冊所有需要反射的類颠区,然后就可以使用類名字符串來創(chuàng)建這些類的對象了削锰。
THsuanluReflectionFactory<THsuanluBase> HsuanluFactory;
//---------------------------------------------------------------------------
__fastcall TForm1::TForm1(TComponent* Owner)
    : TForm(Owner)
{
    HsuanluFactory.Register<THsuanluTest1>();
    HsuanluFactory.Register<THsuanluTest2>();
    HsuanluFactory.Register<THsuanluTest3>();
}
//---------------------------------------------------------------------------
void __fastcall TForm1::Button1Click(TObject *Sender)
{
    THsuanluBase *p1 = nullptr, *p2 = nullptr, *p3 = nullptr;
    try
    {
        p1 = HsuanluFactory.Create(L"THsuanluTest1");
        p2 = HsuanluFactory.Create(L"THsuanluTest2");
        p3 = HsuanluFactory.Create(L"THsuanluTest3");

        p1->PrintMessage();
        p2->PrintMessage();
        p3->PrintMessage();
    }
    catch(Exception &e)
    {
        ShowMessage(e.Message);
    }
    delete p1;
    delete p2;
    delete p3;
}

運行結(jié)果:

運行結(jié)果 - 測試自己寫的類的反射

相關(guān):


C++ Builder 參考手冊 ? C++ Builder 的反射 (二) - Reflection Factory

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市朋截,隨后出現(xiàn)的幾起案子蛹稍,更是在濱河造成了極大的恐慌,老刑警劉巖部服,帶你破解...
    沈念sama閱讀 211,948評論 6 492
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件唆姐,死亡現(xiàn)場離奇詭異,居然都是意外死亡廓八,警方通過查閱死者的電腦和手機奉芦,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,371評論 3 385
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來剧蹂,“玉大人声功,你說我怎么就攤上這事〕璧穑” “怎么了减噪?”我有些...
    開封第一講書人閱讀 157,490評論 0 348
  • 文/不壞的土叔 我叫張陵,是天一觀的道長车吹。 經(jīng)常有香客問我,道長醋闭,這世上最難降的妖魔是什么窄驹? 我笑而不...
    開封第一講書人閱讀 56,521評論 1 284
  • 正文 為了忘掉前任,我火速辦了婚禮证逻,結(jié)果婚禮上乐埠,老公的妹妹穿的比我還像新娘。我一直安慰自己囚企,他們只是感情好丈咐,可當(dāng)我...
    茶點故事閱讀 65,627評論 6 386
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著龙宏,像睡著了一般棵逊。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上银酗,一...
    開封第一講書人閱讀 49,842評論 1 290
  • 那天辆影,我揣著相機與錄音徒像,去河邊找鬼。 笑死蛙讥,一個胖子當(dāng)著我的面吹牛锯蛀,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播次慢,決...
    沈念sama閱讀 38,997評論 3 408
  • 文/蒼蘭香墨 我猛地睜開眼旁涤,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了迫像?” 一聲冷哼從身側(cè)響起劈愚,我...
    開封第一講書人閱讀 37,741評論 0 268
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎侵蒙,沒想到半個月后造虎,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 44,203評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡纷闺,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,534評論 2 327
  • 正文 我和宋清朗相戀三年算凿,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片犁功。...
    茶點故事閱讀 38,673評論 1 341
  • 序言:一個原本活蹦亂跳的男人離奇死亡氓轰,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出浸卦,到底是詐尸還是另有隱情署鸡,我是刑警寧澤,帶...
    沈念sama閱讀 34,339評論 4 330
  • 正文 年R本政府宣布限嫌,位于F島的核電站靴庆,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏怒医。R本人自食惡果不足惜炉抒,卻給世界環(huán)境...
    茶點故事閱讀 39,955評論 3 313
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望稚叹。 院中可真熱鬧焰薄,春花似錦、人聲如沸扒袖。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,770評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽季率。三九已至野瘦,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間飒泻,已是汗流浹背缅刽。 一陣腳步聲響...
    開封第一講書人閱讀 32,000評論 1 266
  • 我被黑心中介騙來泰國打工啊掏, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人衰猛。 一個月前我還...
    沈念sama閱讀 46,394評論 2 360
  • 正文 我出身青樓迟蜜,卻偏偏與公主長得像,于是被迫代替她去往敵國和親啡省。 傳聞我的和親對象是個殘疾皇子娜睛,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 43,562評論 2 349

推薦閱讀更多精彩內(nèi)容