青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品

huaxiazhihuo

 

略說成員函數指針及其模板的精簡實現

    請容許先發一句牢騷,“這萬惡的成員函數指針的丑陋語法!”,C中的函數指針的語法已經夠難看的了,但相比之下,成員函數指針卻更加不堪入目,使用上又很不方便,很不人性化,簡直是只能行走寸步。只可惜,函數指針的作用實在太大了,忽視不得。
    大家都知道,函數指針(或又叫回調函數)是上層模塊和底層模塊進行通信的最佳手段,上層通過提供函數指針給底層,以使得底層在適當的時候,可以調用執行上層的代碼,C庫中的qsort足以說明這種使用,qsort在排序時,不知道如何比較兩個數組元素的大小,必須通過上層提供的大小比較函數來進行比較。此外,操作系統提供的API中,有多少地方使用上了回調函數。假如沒有函數指針,這簡直沒法想像,日子沒法過了。函數指針是實現模塊分層的不二法門,當然接口也可以,但是,用戶代碼必須繼承或者實現底層硬性規定無理取鬧的虛函數,本來很輕量級的POD,再也不輕快了,實在頗不方便,不,簡直很有點惡心。說來說去,還是函數指針好。
    既然,C中的回調函數這么重要,那么,可想而知,進入C++中,整個世界到處都是CLASS,將回調函數這個概念推廣到CLASS上,也即是成員函數指針,將是多么迫切的事情。理論上,可以將成員函數指針視為函數指針的語法糖,只要規定函數指針的第一個參數為void* pThis,然后在函數指針的實現函數中,進行類型轉換也能滿足使用,在很長的一段時間里,因為這種方式的簡單清晰,一直都用這種方式代替成員函數指針。但是,一遍又一遍地被迫編寫重復代碼,特別是枯燥的類型轉換,任何人都無法忍受。因此,決定直面這個問題。
    理論上,成員函數和普通函數一樣,在內存中,都有自己的位置,只要有了地址信息,就可以通過指針來獲取,保存起來,然后在未來的某個地方,通過這個指針來執行函數中的代碼。差別之處,在于,調用成員函數前,要先將this推入ecx中,很久之前,成員函數指針確實和普通函數指針一樣簡單,只是后來,虛函數和多繼承出現之后,簡單的指針信息再也承載不了成員函數的重量,從此之后,.......(忽略,請大家自行BAIDU)。總之,C++中,成員函數指針并非指針類型,理所當然,也就不支持指針的大多數操作,比如,賦值NULL,或者類型轉換。因此,所有能夠讓函數指針大放異彩的種種手段,在這里,都用不上了,原本在C中光芒四射的好東西,到了C++中,竟然黯然失色,所有本該讓函數指針大顯身手的地方,大家都繞道而行。
    逼急了,也有嘗試突破,MFC的僅僅作了有限爭取的手段(為了這一點點好處,MFC可不知作了多大的努力),居然成為其消息映射的基石。但是,據說,MFC的成員函數指針的設計也非出于自愿,而是因為消息太多,實在沒法整成虛函數來處理,每個窗口類背負成千上萬個函數的虛函數表,可不是省油的燈。為了努力地支持虛函數和多繼承,C++的編譯器不惜在成員函數指針的使用上設下種種阻攔,令人又氣又恨。而更加令人不解的是,C++橫行天下十幾年,函數指針似乎長期得不到重視,大師們都在面向對象上探索,很多本該成員函數指針發光發熱的地方,幾乎都退位給虛函數了,并美其名曰策略模式又或者是其他的什么模式,不過是換了一套更加難看的馬甲,卻又那么好聽的名字,不,不好聽,只要聽到模式兩字,就令人大倒胃口。所有大用特用模式的代碼,如果用非模式來實現,其代碼量將少掉很多,而且還更具擴展性,這是真的。先透露一下,正在構思一文章,將深度介紹模式,專注于WHY,并且類比現實,兼扯上WINDOWS、COM和MFC對模式的應用,說句良心話,如果只用接口來做設計,模式絕對是好東西。只可惜,接口其實是SB。寫底層代碼,如果要求用戶必須實現某些接口,又或者是繼承某些類,改寫虛函數,這種侵入式的設計,實在無理取鬧之至。
    后來,大伙兒也終于開始重視成員函數指針,特別是C#的委托出現之后,網絡上更是充斥著各種成員函數指針的版本代碼,都可以很好地完成任務。特別是TR1又或者是BOOST中的function,功能相當的強悍得令人非大吃一驚不可。只可惜,大多數情況下,用戶只想填飽肚子而已,但是BOOST或者其他的類庫卻硬要來一桌滿漢全席,這也罷了,但是,它還要用戶額外買單,并且還真不低呢,這就很讓人受不了啦。其實,一般情況下,我們的要求不會太過分,僅僅想要針對普通的成員函數指針進行回調,它卻為此在其內部new一個內部類出來,假如大規模使用,后果將不堪設想,其實也沒那么嚴重,完成是C++迷們的強迫癥。
    但是,說真的,實在希望很精簡,不要生成不必要的虛函數表,不要模板生成不必要的函數(沒辦法內聯,有函數地址的那一種),只要求它如同對待C中的函數指針一樣,參數入棧和一個簡單的函數調用的指令,外加將this推入ecx即可,就好像直接調用成員函數那樣就好了。好了,貢獻上代碼了,史上最輕量級,精簡無比的成員函數指針,功能也最弱了。對不起,代碼并不完整,實際的代碼,用上了宏,所謂的宏的圖靈完備。在下很懶,一向只介紹想法而已,只于具體的實現細節以及語法考究,竊以為,每個C++迷們應該完全能夠勝任。俗話說,高手只要求創意就行了,本文詳細介紹算法并給出代碼,已經落了下乘。
    這個實現,不考慮多繼承,忽略了虛函數,也不支持非成員函數(也可以用上,只是,要多做一點點手腳,以下將給出示例,而且,普通函數指針已經完全可以勝任),只集中火力專注于普通成員函數,畢竟,在下的運用中,它占上了95%以上,所以才能如此的高效。單一職責啊!
    此外,本文參考了《成員函數指針與高性能的C++委托》、《劉未鵬的BOOST源碼解析》、《C++設計新思維》,請自行GOOGLE。
template <class OutputClass, class InputClass>
union horrible_union{
    OutputClass 
out;
    InputClass 
in;
};

template 
<class OutputClass, class InputClass>
inline 
void union_cast(OutputClass& outconst InputClass input){
    horrible_union
<OutputClass, InputClass> u;
    typedef 
int ERROR_CantUseHorrible_cast[sizeof(InputClass)==sizeof(u) 
        
&& sizeof(InputClass)==sizeof(OutputClass) ? 1 : -1];
    u.
in = input;
    
out = u.out;
}

template
<typename FuncSignature>class TMemFn;
class CCallbackObject{};

template
<typename R>
class TMemFn<R ()>
{
public:
    typedef R ReturnType;
    ReturnType 
operator()() const{return (pThis->*func)();}

    template
<typename _Ty>
    
void Bind(_Ty* pObj, R(_Ty::*proc)())
    {
        union_cast(pThis, pObj);
        union_cast(func, proc);
    }

public:
    typedef ReturnType (CCallbackObject::
*FuncType)();
    FuncType func;
    CCallbackObject
* pThis;
};

template
<typename R, typename P1>
class TMemFn<R (P1)>
{
public:
    typedef R ReturnType;
    typedef P1 Param1Type;

    ReturnType 
operator()(Param1Type param1) const{return (pThis->*func)(param1);}

    template
<typename _Ty>
    
void Bind(_Ty* pObj, ReturnType(_Ty::*proc)(Param1Type))
    {
        union_cast(pThis, pObj);
        union_cast(func, proc);
    }

public:
    typedef ReturnType (CCallbackObject::
*FuncType)(Param1Type);
    FuncType func;
    CCallbackObject
* pThis;
};

template
<typename R, typename _Ty>
TMemFn
<R ()> MakeMF(_Ty* pThis, R(_Ty::*proc)())
{
    TMemFn
<R ()> res; res.Bind(pThis, proc);
    
return res;
}

template
<typename R, typename _Ty, typename P1>
TMemFn
<R (P1)> MakeMF(_Ty* pThis, R(_Ty::*proc)(P1))
{
    TMemFn
<R (P1)> res;res.Bind(pThis, proc);
    
return res;
}

int Test(int a)
{
    printf(
"Hello World %d\n", a);
    
return a;
}

int _tmain(int argc, _TCHAR* argv[])
{
    
class _CTest
    {
    
public:
        
int CallTest(int a)
        {
            
return Test(a);
        }
    };
    TMemFn
<int (int)> aTest = MakeMF((_CTest*)NULL, &_CTest::CallTest);
    aTest(
80);
    
return 0;
}

posted on 2012-11-16 10:46 華夏之火 閱讀(2956) 評論(4)  編輯 收藏 引用 所屬分類: c++技術探討

評論

# re: 略說成員函數指針及其模板的精簡實現 2012-11-16 17:32 Richard Wei

還是直接用C++ 11中的function吧  回復  更多評論   

# re: 略說成員函數指針及其模板的精簡實現 2012-11-16 17:55 華夏之火

@Richard Wei
直接用function,會有心理負擔,雖然沒有必要  回復  更多評論   

# re: 略說成員函數指針及其模板的精簡實現 2012-11-22 07:39 fzy

其實一切源于

typedef TRET (TClass::*P_METHOD)( TPARAM... );
typedef TRET (__cdecl *P_FUNC_CDECL)( TPARAM... );
typedef TRET (__stdcall * P_FUNC_STDCALL)( TPARAM... );
typedef TRET (__fastcall * P_FUNC_FASTCALL)( TPARAM... );

剩下的就是解決
TRET 和 TPARAM... 類型以及 P_METHOD/P_FUNC_XXXXX 的打包問題。

中間比較繁瑣的是 TRET 的void 特例,以及TPARAM...的傳參類型。

在某些特定環境下,還需要考慮TPARAM...的存儲類型。

不過c++的template有特化來實現這些東西,所以最后都歸結到工作量了。  回復  更多評論   

# re: 略說成員函數指針及其模板的精簡實現 2012-11-22 09:27 華夏之火

@fzy
有必要支持那么多嗎,只要typedef TRET (TClass::*P_METHOD)( TPARAM... )這一個就行了,void 確實比較特別  回復  更多評論   

導航

統計

常用鏈接

留言簿(6)

隨筆分類

隨筆檔案

搜索

積分與排名

最新評論

閱讀排行榜

評論排行榜

青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品
  • <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>
            在线日韩欧美视频| 午夜激情综合网| 久久久久综合| 在线播放亚洲| 欧美激情一区二区三区成人| 久久影院午夜论| 亚洲国内在线| 日韩小视频在线观看| 国产精品国产a| 久久精彩免费视频| 老司机精品福利视频| 亚洲美女性视频| 亚洲免费在线观看视频| 一区在线免费观看| 亚洲乱码久久| 国产一区三区三区| 亚洲人精品午夜在线观看| 欧美日韩18| 久久九九免费| 欧美激情一区二区三区在线| 午夜免费电影一区在线观看| 久久久综合视频| 午夜精品久久久久久久久久久久久| 欧美制服第一页| 一区二区欧美激情| 久久久www免费人成黑人精品 | 久久经典综合| 999亚洲国产精| 久久www成人_看片免费不卡| 一区二区三区精品| 久久人人精品| 亚洲一区二区视频在线观看| 久久精品成人| 亚洲欧美日韩一区二区在线 | 新狼窝色av性久久久久久| 99国产一区二区三精品乱码| 欧美一区二区三区四区在线| 中文在线资源观看网站视频免费不卡| 久久福利资源站| 亚洲欧美日韩精品久久久| 欧美激情精品久久久久久免费印度 | 国产欧美精品在线观看| 亚洲黄色在线看| 伊人久久大香线蕉综合热线 | 亚洲国产精品久久久| 国产在线视频欧美| 亚洲性色视频| 一本久久综合亚洲鲁鲁| 美女国产一区| 久久亚洲国产精品一区二区| 国产精品欧美久久| 国产精品99久久久久久www| 欧美91福利在线观看| 亚洲高清在线观看| 国产伪娘ts一区| 亚洲欧美中文日韩v在线观看| 在线一区二区三区做爰视频网站| 美女亚洲精品| 欧美二区在线| 亚洲国产专区| 久久综合九九| 免费看精品久久片| 一区二区三区无毛| 久久亚洲电影| 欧美激情一区三区| 亚洲黄色在线看| 欧美高清视频| 日韩写真在线| 亚洲欧美久久久久一区二区三区| 欧美视频官网| 亚洲一区二区高清视频| 午夜精品国产| 国产毛片一区二区| 欧美影院成年免费版| 久久亚洲不卡| 亚洲精品一区二区三区不| 欧美国产日本| 这里只有精品在线播放| 久久国产精品一区二区三区四区| 国产视频自拍一区| 久久婷婷综合激情| 亚洲欧洲日产国产网站| 亚洲一区二区三区精品在线观看| 国产精品国产三级欧美二区| 香蕉成人啪国产精品视频综合网| 久久亚洲欧洲| 一本色道久久综合亚洲精品婷婷 | 亚洲欧洲久久| 欧美视频免费在线| 欧美一级一区| 欧美黄色影院| 性亚洲最疯狂xxxx高清| 亚洲第一精品电影| 欧美日韩视频专区在线播放 | 久久久久在线观看| 亚洲激情中文1区| 午夜精品一区二区在线观看| 狠狠爱成人网| 欧美特黄a级高清免费大片a级| 午夜精品久久久久久久久久久| 美女尤物久久精品| 亚洲一区精彩视频| 精品91久久久久| 国产精品hd| 久久噜噜噜精品国产亚洲综合 | 久久久亚洲高清| 一本色道久久| 在线视频国产日韩| 国产精品久久久久久久久久免费| 久久嫩草精品久久久精品一| 亚洲天堂男人| 最新日韩欧美| 久久综合成人精品亚洲另类欧美| 亚洲一区二三| 午夜精品久久久久| 国产精品视频第一区| 午夜精品久久一牛影视| 亚洲欧洲在线播放| 麻豆成人在线播放| 欧美一区二区三区免费在线看| 亚洲日本va在线观看| 狠狠色综合网| 国产日韩欧美视频| 国产精品久久久久久妇女6080| 欧美国产一区在线| 久久精品视频免费播放| 亚洲已满18点击进入久久| 日韩视频免费大全中文字幕| 欧美国产一区二区三区激情无套| 久久这里有精品视频| 久久精品国产第一区二区三区最新章节 | 欧美日韩精品三区| 免费不卡在线观看av| 久久久久久有精品国产| 欧美一级播放| 欧美一级大片在线观看| 午夜国产精品视频免费体验区| 宅男噜噜噜66国产日韩在线观看| 日韩午夜精品视频| 亚洲老板91色精品久久| 亚洲精品国产精品乱码不99按摩| 亚洲国产欧美一区二区三区同亚洲 | 国产精品二区在线观看| 欧美三区不卡| 国产精品日韩欧美| 国产精品一区久久久| 国产色视频一区| 国产日韩欧美一区二区三区四区| 国产欧美精品日韩| 国产一区二区三区精品欧美日韩一区二区三区| 国产精品xvideos88| 国产精品成人一区二区三区夜夜夜 | 一区二区三区中文在线观看| 在线观看国产日韩| 中日韩美女免费视频网址在线观看| 亚洲国产精品成人一区二区| 亚洲国产一区二区三区青草影视| 永久久久久久| 日韩一级免费观看| 亚洲影视九九影院在线观看| 欧美资源在线观看| 麻豆久久精品| 亚洲精品一区二区三| 亚洲一区二区三区免费在线观看| 午夜在线精品偷拍| 久久在线免费观看| 欧美连裤袜在线视频| 国产精品久久99| 国内精品伊人久久久久av一坑| 亚洲国产日韩综合一区| 一区二区三区久久| 久久精品视频播放| 亚洲福利视频网站| 亚洲专区一二三| 欧美aaaaaaaa牛牛影院| 欧美深夜影院| 在线精品国产欧美| 午夜精品亚洲一区二区三区嫩草| 久久香蕉精品| 一本色道久久综合亚洲精品婷婷 | 亚洲一区二区四区| 亚洲清纯自拍| 狠狠色2019综合网| 一本久久a久久精品亚洲| 久久国产福利国产秒拍| 最近看过的日韩成人| 先锋资源久久| 欧美日韩免费在线| 伊人色综合久久天天五月婷| 亚洲一区精品在线| 欧美黄色免费网站| 久久不射中文字幕| 国产精品久久久久久影视| 亚洲日本va午夜在线影院| 久久精品日韩一区二区三区| 99视频一区二区| 欧美精彩视频一区二区三区| 黄色精品在线看| 欧美中文字幕视频在线观看| 日韩亚洲不卡在线|