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

隨筆-162  評(píng)論-223  文章-30  trackbacks-0
C與C++ API的比較
   在c語(yǔ)言中,API體現(xiàn)為c函數(shù),如操作系統(tǒng)提供的一系列API,在c++中,API體現(xiàn)為自由函數(shù),這里的自由函數(shù)是指除普通成員函數(shù)、靜態(tài)成員函數(shù)、友元函數(shù)外的能在某命名空間作用域或全局空間內(nèi)直接訪問(wèn)的函數(shù),而這更多地體現(xiàn)為函數(shù)模板,如stl提供的一系列算法swap、count和sort等。相對(duì)于c API,c++ API具有類型安全和封閉開放的優(yōu)點(diǎn),類型安全是因?yàn)閏++本身就是一種比c更強(qiáng)的靜態(tài)類型語(yǔ)言,而封閉開放是指函數(shù)的設(shè)計(jì)實(shí)現(xiàn)一部分是固定的,而另一部分可以是靈活擴(kuò)展的,這表現(xiàn)為函數(shù)模板的重載和全局特化。本文主要講述如何運(yùn)用函數(shù)模板來(lái)設(shè)計(jì)應(yīng)用程序API,并以windows平臺(tái)為例說(shuō)明。

Windows雙版本API

   在windows中,很多API通常都有ANSI和UNICODE兩種字符集形式,其命名對(duì)應(yīng)為xxxA和xxxW。如果應(yīng)用層需要針對(duì)這些API來(lái)封裝,為完備起見,就需要考慮ANSI和UNICODE兩種版本。一般有兩種方法:第一種是先實(shí)現(xiàn)一個(gè)A(或W)版本,而W(或A)版本的實(shí)現(xiàn)則是在其內(nèi)部將UNICODE(或ANSI)型數(shù)化轉(zhuǎn)化為ANSI(或UNICODE)類型,再調(diào)用A(或W)版本,這種方法因需要作字符集的轉(zhuǎn)換來(lái)實(shí)現(xiàn),因而效率較低;第二種是兩個(gè)版本平行實(shí)現(xiàn),即A版本調(diào)用系統(tǒng)A版本API實(shí)現(xiàn),W版本調(diào)用系統(tǒng)W版本API實(shí)現(xiàn),這種方法的缺點(diǎn)是結(jié)果產(chǎn)生除了A或W API調(diào)用不同外很多的重復(fù)代碼。在A和W版本都實(shí)現(xiàn)后,進(jìn)一步,可根據(jù)編譯器的宏定義_UNICODE或UNICODE來(lái)定義一個(gè)自己的API宏。那么除以上兩種方法外,還有沒有更好的方法呢?而這種方法必然要能夠兼顧效率和避免代碼的重復(fù)冗余。在使用這個(gè)方法前,有下列幾個(gè)問(wèn)題:
   1)如何根據(jù)泛型參數(shù)來(lái)選擇定義正確的結(jié)構(gòu)體,因?yàn)橛行┫到y(tǒng)API的參數(shù)中不僅字符串類型有A和W兩種類型,而且凡是其內(nèi)部包含字符串類型的結(jié)構(gòu)體因而也帶有A和W兩種類型。
   2)如何根據(jù)泛型參數(shù)來(lái)選擇調(diào)用正確版本的系統(tǒng)API。
   針對(duì)第1個(gè)問(wèn)題,泛型參數(shù)通常只有A或W兩種,因此可以使用選擇特征類模板來(lái)實(shí)現(xiàn),如boost中的if_c,softstl中的select_first_type類模板,也可以自己實(shí)現(xiàn)這樣的類模板。對(duì)第2個(gè)問(wèn)題,與第1個(gè)問(wèn)題不同的是,它是選擇函數(shù)而不是類型,本質(zhì)上就是選擇變量,因此需要實(shí)現(xiàn)一種基于類型或非類型參數(shù)選擇變量的模板,并且使用方式如下
    select_variable<flag>(xxxA,xxxW)(arg1,arg2,...,argN)
   flag是一個(gè)布爾非類型模板實(shí)參,當(dāng)值為true時(shí)表示選擇返回xxxA,反之選擇返回xxxW,然后接下來(lái)跟著一系列參數(shù),表示調(diào)用對(duì)應(yīng)的A或W版本API,因此select_variable應(yīng)該實(shí)現(xiàn)為函數(shù)模板比較方便,若實(shí)現(xiàn)為類模板(關(guān)于實(shí)現(xiàn)可以參考boost中的function),則需要顯式指定函數(shù)返回值和參數(shù)類型,這樣一來(lái),當(dāng)函數(shù)參數(shù)過(guò)多,就是一個(gè)噩夢(mèng)了,因?yàn)?/span>模板實(shí)參演繹不能用于類模板及其構(gòu)造函數(shù),只能應(yīng)用于其成員函數(shù)模板
   綜上分析解決,下面給出select_variable的實(shí)現(xiàn)與應(yīng)用。

select_variable實(shí)現(xiàn)
   使用類模板特化與函數(shù)模板重載技術(shù)
 1#define TEMPLATE_BOOL_TRAIT_DEF1(trait,T,c)\
 2template<typename T>\
 3struct trait\
 4{\
 5    static const bool value=c;\
 6}
;\
 7
 8#define TEMPLATE_BOOL_TRAIT_SPEC1(trait,sp,c)\
 9template<>\
10struct trait<sp>\
11{\
12    static const bool value=c;\
13}
;\
14
15template<bool flag,typename T1,typename T2>
16struct select_type;
17
18template<typename T1,typename T2>
19struct select_type<true,T1,T2>
20{
21    typedef T1 type;
22}
;
23
24template<typename T1,typename T2>
25struct select_type<false,T1,T2>
26{
27    typedef T2 type;
28}
;
29
30template<bool flag,typename T1,typename T2>
31inline typename select_type<flag,T1,T2>::type select_variable(T1 t1,T2 t2)
32{
33    return select_variable_impl(typename select_type<flag,int,long>::type(),t1,t2);
34}

35
36template<typename T1,typename T2>
37inline T1 select_variable_impl(int,T1 t1,T2 t2)
38{
39    return t1;
40}

41
42template<typename T1,typename T2>
43inline T2 select_variable_impl(long,T1 t1,T2 t2)
44{
45    return t2;
46}

47
48TEMPLATE_BOOL_TRAIT_DEF1(is_ansi_char,T,false)
49TEMPLATE_BOOL_TRAIT_SPEC1(is_ansi_char,char,true)
50TEMPLATE_BOOL_TRAIT_SPEC1(is_ansi_char,char const,true)
51TEMPLATE_BOOL_TRAIT_SPEC1(is_ansi_char,char volatile,true)
52TEMPLATE_BOOL_TRAIT_SPEC1(is_ansi_char,char const volatile,true)
53
54#undef TEMPLATE_BOOL_TRAIT_DEF1
55#undef TEMPLATE_BOOL_TRAIT_SPEC1
   
select_variable應(yīng)用
   有了select_variable,封裝設(shè)計(jì)API就方便多了,在函數(shù)模板中,類型的參數(shù)化體現(xiàn)在其參數(shù)、返回值和內(nèi)部實(shí)現(xiàn)三方面,下面就從這三方面來(lái)說(shuō)明其應(yīng)用:
   參數(shù)類型化
   IsDirectoryOrFile根據(jù)路徑來(lái)判斷是否為目錄或文件,對(duì)于調(diào)用方來(lái)說(shuō),可以靈活指定A或W版本的字符串路徑。
1template<typename charT>
2inline int IsDirectoryOrFile(const charT* path)
3{
4    DWORD dwFlag = select_variable<is_ansi_char<charT>::value>(GetFileAttributesA,GetFileAttributesW)(path);
5    if (INVALID_FILE_ATTRIBUTES == dwFlag)   
6        return 0;   
7    return (dwFlag & FILE_ATTRIBUTE_DIRECTORY) ? 1 : 2;
8}
  
   返回值類型化
   GetExePath獲取當(dāng)前應(yīng)用程序的路徑,對(duì)于調(diào)用方來(lái)說(shuō),可以靈活指定想要返回A或W版本字符串表示的路徑。
1template<typename T>
2inline std::basic_string<T> GetExePath()
3{
4    T szExePath[MAX_PATH];
5    select_variable<is_ansi_char<T>::value>(GetModuleFileNameA,GetModuleFileNameW)(NULL,szExePath);
6    return szExePath;
7}
   
   內(nèi)部實(shí)現(xiàn)類型化
   GetDirSize計(jì)算某一目錄或文件的大小,因內(nèi)部用到了FirstFirstFile和FirstNextFile,而這兩個(gè)API不僅路徑,而且WIN32_FIND_DATA結(jié)構(gòu)體都有A和W版本,因此需要選擇定義正確的結(jié)構(gòu)體變量和調(diào)用正確的API函數(shù)。
 1template<typename charT>
 2inline ULONGLONG GetDirSize(const charT* path, const volatile BOOL& bExitCalc)
 3{
 4    int ret = IsDirectoryOrFile(path);
 5    if (0==ret) return 0L;
 6
 7    std::basic_string<charT>  strPath = path;
 8    if (1==ret)
 9    {
10        if (strPath.length() - 1 != strPath.rfind((charT)'\\'))
11            strPath += (charT)'\\';
12        strPath += select_variable<is_ansi_char<charT>::value>("*.*",L"*.*");
13    }

14    ULONGLONG ullSumSize = 0;
15    typename select_type<is_ansi_char<charT>::value,WIN32_FIND_DATAA,WIN32_FIND_DATAW>::type findData;
16    HANDLE hFindFile = select_variable<is_ansi_char<charT>::value>(FindFirstFileA,FindFirstFileW)(strPath.c_str(), &findData);
17
18    for(BOOL bResult = (hFindFile != INVALID_HANDLE_VALUE); bResult; bResult = select_variable<is_ansi_char<charT>::value>(FindNextFileA,FindNextFileW)(hFindFile, &findData))
19    {
20        if(findData.cFileName[0== (charT)'.'
21            continue;
22        if(findData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
23        {
24            strPath = strPath.substr(0,strPath.rfind((charT)'\\')+1)+findData.cFileName;
25            ullSumSize += GetDirSize(strPath.c_str(), bExitCalc);
26        }

27        else
28            ullSumSize += (((ULONGLONG)findData.nFileSizeHigh) << 32+ findData.nFileSizeLow;
29    }

30    ::FindClose(hFindFile);  
31    return ullSumSize;
32}
posted on 2011-12-24 19:08 春秋十二月 閱讀(2978) 評(píng)論(2)  編輯 收藏 引用 所屬分類: C/C++

評(píng)論:
# re: 模板應(yīng)用(1) API的設(shè)計(jì)與函數(shù)模板 2011-12-24 21:24 | 萬(wàn)連文
模板這么用有點(diǎn)浪費(fèi)(幾乎是只有一種API調(diào)用方式的實(shí)例化),理論上講你不應(yīng)該在你的代碼中使用MBSC編碼,應(yīng)該采用Unicode編碼,牽扯到的字符使用wchar或者utf8。
模板最好用在架構(gòu)的底層設(shè)計(jì)設(shè)施上,大多是面向語(yǔ)言層面或者純軟件設(shè)計(jì)領(lǐng)域。  回復(fù)  更多評(píng)論
  
# re: 模板技術(shù)與應(yīng)用(1): API的設(shè)計(jì) 2012-06-25 16:55 | liyou
看著就頭大  回復(fù)  更多評(píng)論
  
青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品
  • <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>
            欧美精品一区二区三区久久久竹菊| 亚洲激情黄色| 国产亚洲一二三区| 国产精品视频一二三| 国产精品一二一区| 国产日韩精品久久久| 国产精品一级在线| 精品91免费| 日韩亚洲国产精品| 亚洲欧美卡通另类91av| 久久精品成人欧美大片古装| 久久综合99re88久久爱| 欧美激情在线| 亚洲欧美清纯在线制服| 久久久久久久久久久久久久一区 | 欧美福利视频| 亚洲福利久久| 亚洲午夜精品一区二区| 在线不卡亚洲| 欧美亚日韩国产aⅴ精品中极品| 国产精品免费网站在线观看| 在线电影国产精品| 亚洲图片欧美午夜| 免费中文字幕日韩欧美| 中文国产成人精品| 久热精品在线视频| 国产精品一级二级三级| 亚洲精品老司机| 久久精品视频在线观看| 日韩视频中文| 久久影院午夜论| 国产精品视频成人| 99精品欧美一区二区三区 | 亚洲欧洲日本国产| 欧美在线3区| 亚洲另类春色国产| 麻豆精品精华液| 国语自产偷拍精品视频偷| 亚洲欧美日韩精品综合在线观看| 欧美激情第五页| 欧美专区在线播放| 国产精品亚洲综合一区在线观看 | 亚洲精品欧洲| 久久在线精品| 国产自产女人91一区在线观看| 亚洲视频在线观看一区| 亚洲大胆女人| 久久久久久久久久久一区| 国产欧美日本一区视频| 亚洲中字在线| 99热精品在线| 国产精品初高中精品久久| 一区二区三区视频在线| 亚洲青涩在线| 欧美精品日韩| 一区二区三区精品国产| 99视频一区二区三区| 欧美日韩国产综合视频在线观看中文 | 欧美成人三级在线| 狠狠综合久久| 久久理论片午夜琪琪电影网| 久久aⅴ国产紧身牛仔裤| 国产字幕视频一区二区| 久久影视三级福利片| 久久九九精品99国产精品| 国产亚洲成精品久久| 欧美一区二区视频在线| 国产女主播一区| 久久精品国产清高在天天线| 欧美在线视频在线播放完整版免费观看 | 亚洲一级二级在线| 国产伦精品一区二区三区视频黑人 | 欧美二区在线播放| 日韩一区二区免费高清| 亚洲精品乱码久久久久久蜜桃91| 欧美高清在线视频| 亚洲欧美激情精品一区二区| 午夜精品视频在线观看| 红杏aⅴ成人免费视频| 欧美黄色一区二区| 欧美精品v国产精品v日韩精品| 亚洲深夜av| 欧美一级播放| 亚洲免费av电影| 亚洲淫性视频| 在线国产欧美| 亚洲最新色图| 一区二区视频欧美| 亚洲精品无人区| 国产精品自拍小视频| 欧美bbbxxxxx| 国产精品久久国产精品99gif | 亚洲一区二区三区精品在线| 国精产品99永久一区一区| 欧美激情第五页| 国产精品腿扒开做爽爽爽挤奶网站| 久久午夜电影网| 欧美日韩在线第一页| 另类av一区二区| 国产精品高清网站| 欧美成人免费在线| 国产精品久久一区主播| 免费在线观看日韩欧美| 欧美性片在线观看| 欧美高清视频一二三区| 国产精品久久久久9999高清| 欧美国产日韩精品免费观看| 国产精品区一区二区三| 亚洲人成毛片在线播放| 好看不卡的中文字幕| 亚洲一区视频在线| 一区二区不卡在线视频 午夜欧美不卡'| 亚洲影院色在线观看免费| 日韩一区二区精品视频| 蜜臀久久久99精品久久久久久| 欧美专区在线观看一区| 欧美午夜精品久久久久久久 | 国产精品卡一卡二| 亚洲精品社区| 久久九九国产精品| 羞羞答答国产精品www一本| 欧美精品www| 欧美国产第二页| 韩日午夜在线资源一区二区| 亚洲已满18点击进入久久| 亚洲视频在线观看网站| 欧美精品日韩一区| 亚洲国产精品精华液2区45 | 国产一区二区在线观看免费播放 | 久久九九免费视频| 国产乱码精品一区二区三区不卡| 99视频精品| 亚洲一区二区三区在线看| 欧美日韩国产免费观看| 亚洲美女电影在线| 亚洲一级片在线看| 国产精品久久久久久久第一福利 | 欧美精品福利在线| 亚洲第一狼人社区| 亚洲欧洲在线一区| 欧美成人蜜桃| 亚洲精品专区| 亚洲婷婷在线| 国产精品欧美一区二区三区奶水| 夜夜嗨av一区二区三区四区| 亚洲午夜影视影院在线观看| 国产精品二区在线| 午夜精品在线观看| 麻豆国产精品777777在线| 亚洲国产精品女人久久久| 欧美二区在线播放| 在线视频免费在线观看一区二区| 亚洲欧美成人在线| 韩日精品视频| 欧美激情一二三区| 亚洲一区二区三区四区在线观看 | 这里只有精品视频在线| 国产精品极品美女粉嫩高清在线 | 久久免费视频网| 欧美gay视频激情| 日韩亚洲国产欧美| 国产欧美日韩综合一区在线播放| 久久国内精品视频| 亚洲日产国产精品| 欧美一区二区女人| 亚洲电影免费| 国产精品高清免费在线观看| 久久激情综合网| 亚洲欧洲一区| 欧美专区18| av不卡在线观看| 红桃视频成人| 国产精品久久久一本精品| 久久在精品线影院精品国产| 亚洲毛片视频| 麻豆成人综合网| 亚洲桃花岛网站| 伊人夜夜躁av伊人久久| 欧美私人网站| 久久日韩精品| 狠狠色狠狠色综合| 欧美人在线观看| 久久精品夜夜夜夜久久| 日韩天天综合| 欧美丰满少妇xxxbbb| 欧美在线视频日韩| 在线视频亚洲一区| 亚洲福利视频网| 国产性色一区二区| 国产精品久久久久久亚洲毛片| 暖暖成人免费视频| 久久久久久久一区二区| 亚洲欧美成人一区二区在线电影| 91久久精品国产91性色| 美女福利精品视频| 久久久精品一区| 欧美一区二区大片| 亚洲欧美日韩国产成人精品影院| 日韩系列在线| 99国产精品视频免费观看|