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

Beginning to 編程

VC++ 方面編程文章

 

轉(zhuǎn)換大小寫C函數(shù)

?

Richard zeng? 3/19/2006 10:50:36 AM

?

這幾天又把以前的 C 課程翻了出來 , 因為自己對 C 的指針和數(shù)組不是很 DEV.

模擬 C 庫函數(shù)中的轉(zhuǎn)化大小寫函數(shù) .

?

// 轉(zhuǎn)換成大寫 , 函數(shù)參數(shù)為字符數(shù)組

// 利用字符串?dāng)?shù)組的結(jié)尾都是 \0

void ToUpper(chars[])

{

?????? int i=0;

?????? while(s[i++]!='\0' )

?????? {

????????????? // 判斷是否是小寫字母

????????????? if(s[i]>='a' && s[i]<='z' )

???????????????????? s[i] -= 32;???? // 小寫字母比大寫字母的 ASCII 32

?????? }

}

?

// 轉(zhuǎn)換成大寫 , 函數(shù)參數(shù)為字符指針

void ToUpperPtr(char* s)

{

?????? while(*s != '\0')

?????? {

// 判斷是否是小寫字母

????????????? if(*s >='a' && *s <='z')

???????????????????? *s -= 32; ???? // 小寫字母比大寫字母的 ASCII 32

????????????? s++; // 指針的地址 ++

?????? }

}

posted @ 2006-03-19 10:56 Beginning to 編程 閱讀(5871) | 評論 (5)編輯 收藏

波形顯示不是很難 /zhuan

封裝了一下波形顯示,發(fā)現(xiàn)不是很難


WaveShow_src.rar

posted @ 2006-03-16 11:00 Beginning to 編程 閱讀(631) | 評論 (1)編輯 收藏

大小寫轉(zhuǎn)換的方法【C/C++】 /zhuan

ASCII碼表大家都很熟悉了吧,利用碼的排列規(guī)律,我們可以很容易的實現(xiàn)一些操作,比如判斷是否是數(shù)字、大小寫轉(zhuǎn)換等。
這里寫大小寫轉(zhuǎn)換的函數(shù):
char toUpper(const char& ch)
{
    return ch & 0x5F;
}
char toLower(const char& ch)
{
    return ch | 0x20;
}
 
函數(shù)原理:大小寫字母的差是32,比如大寫的A是65,小寫的A是97,所以我們把右邊數(shù)第6位置0或者1就能實現(xiàn)大小寫轉(zhuǎn)換。轉(zhuǎn)換成大寫時,把第6位置0,用ch & 0x5F實現(xiàn)。轉(zhuǎn)換成小寫時置1,用ch | 0x20實現(xiàn)。怎么樣,相當(dāng)?shù)暮唵伟桑纱耍覀兛梢詫憇tring類的toUpper和toLower函數(shù)了。^_^,更多技巧盡在探索中。

posted @ 2006-03-15 13:31 Beginning to 編程 閱讀(966) | 評論 (0)編輯 收藏

淺談CMPP協(xié)議(一) /zhuan

    CMPP協(xié)議的全稱是中國移動通信互聯(lián)網(wǎng)短信網(wǎng)關(guān)接口協(xié)議,它是聯(lián)想亞信公司根據(jù)SMMP協(xié)議為中國移動量身定做的,是符合中國國情的一個短信協(xié)議,閑話不多說了,說說CMPP的主要功能吧。(1)短信發(fā)送(short message mobile originate)MO,就是手機給SP發(fā)短信;(2)短信接受(short message mobile terminated)MT,這個就是SP給手機發(fā)的短信了,通常我們手機上收到的不良短信就是SP給我們的MT。CMPP協(xié)議的通信基礎(chǔ)是TCP/IP為底層通信承載的,連接方式是長連接方式。SP與ISMG之間,SMSC和ISMG之間的交互過程中均采用異步方式,即任一個網(wǎng)元在收到請求消息后應(yīng)立即回應(yīng)。
   下面看看它的消息定義:CMPP中的消息分為消息頭和消息體。消息頭定義如下
 
 

字段名

字節(jié)數(shù)

類型

描述

Total_Length  

4

Unsigned Integer

消息總長度(含消息頭及消息體)

Command_Id

4

Unsigned Integer

命令或響應(yīng)類型

Sequence_Id

4

Unsigned Integer

消息流水號,順序累加,步長為1,循環(huán)使用(一對請求和應(yīng)答消息的流水號必須相同)

 
那么下面就是SP連接到ISMG上了,看它的Bind連接消息定義
 

字段名

字節(jié)數(shù)

屬性

描述

Source_Addr 

6

Octet String

源地址,此處為SP_Id,即SP的企業(yè)代碼。

AuthenticatorSource

16

Octet String

用于鑒別源地址。其值通過單向MD5 hash計算得出,表示如下:

AuthenticatorSource =

MD5Source_Addr+9 字節(jié)的0 +shared secret+timestamp

Shared secret 由中國移動與源地址實體事先商定,timestamp格式為:MMDDHHMMSS,即月日時分秒,10位。

Version

1

Unsigned Integer

雙方協(xié)商的版本號(高位4bit表示主版本號,低位4bit表示次版本號),對于3.0的版本,高4bit3,低4位為0

Timestamp

4

Unsigned Integer

時間戳的明文,由客戶端產(chǎn)生,格式為MMDDHHMMSS,即月日時分秒,10位數(shù)字的整型,右對齊

 
根據(jù)上的定義我們可以寫出的代碼,如下,在VC環(huán)境下編寫的

/*
 *函數(shù)功能:建立和CMPP網(wǎng)關(guān)的直接通路
 *輸入條件:SP用戶名const char *UserName,SP密碼const char *PWD 
 */
void Ccmpp_API::CmppConnect(const char *UserName, const char *PWD)
{
 char netbuf[100];
 CMPP_CONNECT *bufer;
 bufer=(CMPP_CONNECT*)netbuf;
 memset(bufer, 0, 100);
 bufer->nTotalLength = htonl(39);//CMPP_CONNECT消息總長度
 bufer->nCommandId = htonl(CMPP_CONNECT_tag);//消息標志
 //自動產(chǎn)生SeqId號
    if (sequenceid == 123456789i32)
 {
  sequenceid = 1;
 }else{
  sequenceid++;
 }
 bufer->nSeqId = htonl(sequenceid);
   
 int MD5Len;
 MD5_CTX md5;//MD5源字串
 CTime TimeData = CTime::GetCurrentTime();
 CString timestamp = TimeData.Format("%m%d%H%M%S");
 unsigned char md5source[29];
 int Len1 = strlen(UserName);
 int Len2 = strlen(PWD); 
 MD5Len = Len1 + 9 +Len2 + timestamp.GetLength();
 memset(md5source, 0, MD5Len);
 
 memcpy(bufer->sSourceAddr, UserName, Len1);
 memcpy(md5source, UserName, Len1);
 
 for (int j = 0; j<Len2; j++)
 {
  md5source[j + Len1 + 9] = PWD[j];
 }
 for (int i=0;i<timestamp.GetLength();i++)
 {
  md5source[i + Len2 + Len1 + 9]=timestamp[i];
 }
 
 //進行md5加密轉(zhuǎn)換
 md5.MD5Update(md5source, MD5Len);
 md5.MD5Final(md5source);
 memcpy(bufer->sAuthSource, md5source, 29);
 bufer->cVersion = 0x30;
 bufer->nTimeStamp = htonl(atoi(timestamp));
 CmppSocket.Send(bufer, 39, 0);//把消息打包發(fā)送
 return;
}
 
今天就到這,下次再寫,歡迎交流!
posted on 2006-03-15 07:58 炙熱的太陽 閱讀(38) 評論(2)  編輯 收藏 收藏至365Key


FeedBack:

# re: 淺談CMPP協(xié)議(一)
2006-03-15 10:38 | 小明
you say:
SP與ISMG之間,SMSC和ISMG之間的交互過程中均采用異步方式,即任一個網(wǎng)元在收到請求消息后應(yīng)立即回應(yīng)。

既然是異步方式,就不是收到請求后立即回應(yīng),否則就是同步方式了

據(jù)我所知,CMPP采用的基于滑動窗口的異步方式,默認情況下可以發(fā)最多16的CMPP package,而不必等待他們的resp.  回復(fù)
  
# re: 淺談CMPP協(xié)議(一)
2006-03-15 11:21 | 炙熱的太陽
是的,你說的沒有錯。

消息是采用并發(fā)方式發(fā)送,加以滑動窗口流量控制,窗口大小參數(shù)W可配置,現(xiàn)階段的配置為16,即接收方在應(yīng)答前一次收到的消息最多不超過16條。這是它們之間的通信方式。

而SP與ISMG之間,SMSC和ISMG之間的交互過程中均采用異步方式,即任一個網(wǎng)元在收到請求消息后應(yīng)立即回應(yīng)。這是它們交互過程中的應(yīng)答方式。即收到一個消息就應(yīng)該回一個回應(yīng)消息,而不管對方是否收到,所以上面講的并沒有錯喲。


  回復(fù)

posted @ 2006-03-15 12:25 Beginning to 編程 閱讀(883) | 評論 (0)編輯 收藏

為什么在VS2005重載輸出運算符那么難 /zhuan

     摘要: 最近在VS2005下實現(xiàn)一個模版堆棧時,想重載一下輸出運算符。結(jié)果老是遇到問題,如何都過不去,想不想去都不明白。還望高手指教。  一開始同樣的程序在VC2005和VC6.0下編譯都沒問題,但是一到鏈接的時候就出現(xiàn)問題了。都提示如下錯誤:       error LNK2019: 無法解析的外部符號 "cla...  閱讀全文

posted @ 2006-03-15 11:57 Beginning to 編程 閱讀(1131) | 評論 (1)編輯 收藏

VC中回調(diào)函數(shù)使用的變身大法 /zhuan

對于回調(diào)函數(shù)的編寫始終是寫特殊處理功能程序時用到的技巧之一。先介紹一下回調(diào)的使用基本方法與原理。

  1、在這里設(shè):回調(diào)函數(shù)為A()(這是最簡單的情況,不帶參數(shù),但我們應(yīng)用的實際情況常常很會復(fù)雜),使用回調(diào)函數(shù)的操作函數(shù)為B(), 但B函數(shù)是需要參數(shù)的,這個參數(shù)就是指向函數(shù)A的地址變量,這個變量一般就是函數(shù)指針。使用方法為:

int A(char *p); // 回調(diào)函數(shù)
typedef int(*CallBack)(char *p) ; // 聲明CallBack 類型的函數(shù)指針
CallBack myCallBack ; // 聲明函數(shù)指針變量
myCallBack = A; // 得到了函數(shù)A的地址

  B函數(shù)一般會寫為 B(CallBack lpCall,char * P,........); // 此處省略了p后的參數(shù)形式 。

  所以回調(diào)機制可解為,函數(shù)B要完成一定功能,但他自己是無法實現(xiàn)全部功能的。 需要借助于函數(shù)A來完成,也就是回調(diào)函數(shù)。B的實現(xiàn)為:

B(CallBack lpCall,char *pProvide)
{
 ........... // B 的自己實現(xiàn)功能語句
 lpCall(PpProvide); // 借助回調(diào)完成的功能 ,也就是A函數(shù)來處理的。
 ........... // B 的自己實現(xiàn)功能語句
}
// -------------- 使用例子 -------------
char *p = "hello!";
CallBack myCallBack ;
myCallBack = A ;
B(A, p);

  以上就是回調(diào)的基本應(yīng)用,本文所說的變身,其實是利用傳入不同的函數(shù)地址,實現(xiàn)調(diào)用者類與回調(diào)函數(shù)所在類的不同轉(zhuǎn)換。

  1、問題描述

  CUploadFile 類完成數(shù)據(jù)上傳,與相應(yīng)的界面進度顯示。

  主要函數(shù)Send(...) 和回調(diào)函數(shù) GetCurState() ;

class CUploadFile : public CDialog
{
 ......
 int Send(LPCTSTR lpServerIP, LPCTSTR lpServerPort, LPCTSTR UploadFilePath) ;
 static int GetCurState(int nCurDone, int nInAll, void * pParam) ;
 ......
}
int CUploadFile ::Send(LPCTSTR lpServerIP, LPCTSTR lpServerPort, LPCTSTR UploadFilePath)
{
 ... // 導(dǎo)出傳輸數(shù)據(jù)的函數(shù)
 int ret = Upload( (LPSTR)(LPCTSTR)m_strData,
    GetCurState, // 在這個回調(diào)函數(shù)中處理界面
    this, // CUploadFile 的自身指針 ,也就是pParam 所接受的參數(shù)
    (LPSTR)(LPCTSTR)UploadFilePath,
    "",
    "",
 );
}
int CUploadFile ::GetCurState(int nCurData, int nInAll, void * pParam)
{
 .........
 UploadFile *pThis = (UploadFile *)pParam; // nCurData 當(dāng)前以傳出的數(shù)據(jù)量
 // nInAll 總的數(shù)據(jù)量
 // 有了pThis可以對界面進行各種操作了。
 .............
}

  但大家仔細觀察就可以發(fā)現(xiàn),這個類把數(shù)據(jù)傳送和界面顯示聚和到了一起,不容易得到復(fù)用。而且在復(fù)用過程中需要改動較多的地方 。

  請大家記住現(xiàn)在的回調(diào)函數(shù)傳入的類本身的靜態(tài)成員函數(shù)。

  現(xiàn)在我們把數(shù)據(jù)的傳送和界面的顯示分離。回調(diào)則要傳入的是界面處理類的靜態(tài)函數(shù)。

  界面處理類 CShowGUI,數(shù)據(jù)上傳類 CUploadData

class CUploadData
{
 ......
 typedef int(*SetUploadCaller)(int nCurData, int nInAll, void * pParam);
 int UploadFile(LPCTSTR lpFileNamePath,LPVOID lparam,SetUploadCaller Caller );
 // 接受外界出入的參數(shù),主要是回調(diào)函數(shù)的地址通過參數(shù)Caller,
 int Send(LPCTSTR lpServerIP, LPCTSTR lpServerPort, LPCTSTR UploadFilePath) ;
 ...... // 注意此時不在需要GetCurState 函數(shù)了 。
}

class CShowGUI: public CDialog
{
 .......
 typedef int(*SetUploadCaller)(int nCurData, int nInAll, void * pParam);
 void SetCallBack(LPCTSTR strPath);
 static int GetCurState(int nCurData, int nInAll, void * pParam) ;
 CUploadData m_Uploa
 d ; // 數(shù)據(jù)上傳類是界面顯示類的一個成員變量。
 .......
}

void CShowGUI :: SetCallBack(LPCTSTR strPath)
{
 CUploadData myUploadData ;
 SetUploadCaller myCaller; // 聲明一個函數(shù)指針變量
 myCaller = CurState ; // 取得界面處理函數(shù)的地址
 myUploadData .UploadFile(strPath,this,myCaller); // 界面處理類的函數(shù)傳入,實現(xiàn)了數(shù)據(jù)傳入與界面處理的分離 .
}

  通過上面的演示做到了界面與數(shù)據(jù)的分離,回調(diào)函數(shù)分別扮演了不同角色,所以隨著處理問題的不同應(yīng)靈活應(yīng)用,但同樣因為處理數(shù)據(jù)類不知道界面處理類或外部調(diào)用類的類型,而更無法靈活地處理界面的不同顯示方式。這方面還希望喜歡鉆研技術(shù)的朋友繼續(xù)研究。陳剛

posted @ 2006-03-14 17:33 Beginning to 編程 閱讀(335) | 評論 (0)編輯 收藏

C++指針探討 (二) 函數(shù)指針 /zhuan

在C/C++中,數(shù)據(jù)指針是最直接,也最常用的,因此,理解起來也比較容易。而函數(shù)指針,作為運行時動態(tài)調(diào)用(比如回調(diào)函數(shù) CallBack Function)是一種常見的,而且是很好用的手段。

  我們先簡單的說一下函數(shù)指針。(這一部份沒什么價值,純是為了引出下一節(jié)的內(nèi)容)
   
 2 常規(guī)函數(shù)指針

        void(*fp)();

  fp 是一個典型的函數(shù)指針,用于指向無參數(shù),無返回值的函數(shù)。

        void(*fp2)(int);

  fp2 也是一個函數(shù)指針,用于指向有一個整型參數(shù),無返回值的函數(shù)。
  當(dāng)然,有經(jīng)驗人士一般都會建議使用typedef來定義函數(shù)指針的類型,如:

        typedef void(* FP)();
        FP fp3; 
// 和上面的fp一樣的定義。

  函數(shù)指針之所以讓初學(xué)者畏懼,最主要的原因是它的括號太多了;某些用途的函數(shù)指針,往往會讓人陷在括號堆中出不來,這里就不舉例了,因為不是本文討論的范圍;typedef 方法可以有效的減少括號的數(shù)量,以及理清層次,所以受到推薦。本文暫時只考慮簡單的函數(shù)指針,因此暫不用到typedef。

  假如有如下兩個函數(shù):

  void f1()
  
{
      std::cout 
<< "call f " << std::endl;
  }

  
  
void f2(int a)
  
{
      std::cout 
<< "call f2( " << a << " )" << std::endl;
  }

  現(xiàn)在需要通過函數(shù)指針來調(diào)用,我們需要給指針指定函數(shù):

  fp = &f1; // 也可以用:fp = f1;
  fp2= &f2; // 也可以用:fp2= f2;
  void (*fp3)() = &f1; // 也可以用:void (*fp3)() = f1;  
  
//調(diào)用時如下:
  fp(); // 或 (*fp)();
  fp2(1); // 或 (*fp2)(1);
  fp3();  // 或 (*fp3)();

  對于此兩種調(diào)用方法,效果完全一樣,我推薦用前一種。后一種不僅僅是多打了鍵盤,而且也損失了一些靈活性。這里暫且不說它。
  
  C++強調(diào)類型安全。也就是說,不同類型的變量是不能直接賦值的,否則輕則警告,重則報錯。這是一個很有用的特性,常常能幫我們找到問題。因此,有識之士認為,C++中的任何一外警告都不能忽視。甚至有人提出,編譯的時候不能出現(xiàn)任何警告信息,也就是說,警告應(yīng)該當(dāng)作錯誤一樣處理。
  
  比如,我們把f1賦值給fp2,那么C++編譯器(vc7.1)就會報錯:

  fp2 = &f1; // error C2440: “=” : 無法從“void (__cdecl *)(void)”轉(zhuǎn)換為“void (__cdecl *)(int)”
  fp1 = &f1; // OK

  這樣,編譯器可以幫我們找出編碼上的錯誤,節(jié)省了我們的排錯時間。
  
  考慮一下C++標準模板庫的sort函數(shù):

  // 快速排序函數(shù)
  template<typename RandomAccessIterator, typename BinaryPredicate>
     
void sort(
        RandomAccessIterator _First, 
// 需排序數(shù)據(jù)的第一個元素位置
        RandomAccessIterator _Last,  // 需排序數(shù)據(jù)的最后一個元素位置(不參與排序)
        BinaryPredicate _Comp     // 排序使用的比較算法(可以是函數(shù)指針、函數(shù)對象等)
     );

  比如,我們有一個整型數(shù)組:

  int n[5= {3,2,1,8,9};

  要對它進行升序排序,我們需定義一個比較函數(shù):

  bool less(int a, int b)
  
{
      
return a < b; 
  }

  然后用:

  sort(n, n+5, less);

  要是想對它進行降序排序,我們只要換一個比較函數(shù)就可以了。C/C++的標準模板已經(jīng)提供了less和great函數(shù),因此我們可以直接用下面的語句來比較:  

  sort(n, n+5, great);


  這樣,不需要改變sort函數(shù)的定義,就可以按任意方法進行排序,是不是很靈活?  
  這種用法以C++的標準模板庫(STL)中非常流行。另外,操作系統(tǒng)中也經(jīng)常使用回調(diào)(CallBack)函數(shù),實際上,所謂回調(diào)函數(shù),本質(zhì)就是函數(shù)指針。

  看起來很簡單吧,這是最普通的C語言指針的用法。本來這是一個很美妙的事情,但是當(dāng)C++來臨時,世界就開始變了樣。
  假如,用來進行sort的比較函數(shù)是某個類的成員,那又如何呢?

posted @ 2006-03-14 16:44 Beginning to 編程 閱讀(339) | 評論 (0)編輯 收藏

C++指針探討 (一)數(shù)據(jù)指針 /zhuan

  指針,在C/C++語言中一直是很受寵的;幾乎找不到一個不使用指針的C/C++應(yīng)用。用于存儲數(shù)據(jù)和程序的地址,這是指針的基本功能。用于指向整型數(shù),用整數(shù)指針(int*);指向浮點數(shù)用浮點數(shù)指針(float*);指向結(jié)構(gòu),用對應(yīng)的結(jié)構(gòu)指針(struct xxx *);指向任意地址,用無類型指針(void*)。
    有時候,我們需要一些通用的指針。在C語言當(dāng)中,(void*) 可以代表一切;但是在C++中,我們還有一些比較特殊的指針,無法用(void*)來表示。事實上,在C++中,想找到一個通用的指針,特別是通用的函數(shù)指針簡直是一個“不可能任務(wù)”。
   
    C++是一種靜態(tài)類型的語言,類型安全在C++中舉足輕重。在C語言中,你可以用void*來指向一切;但在C++中,void*并不能指向一切,就算能,也失去了類型安全的意義了。類型安全往往能幫我們找出程序中潛在的一些BUG。
   
    下面我們來探討一下,C++中如何存儲各種類型數(shù)據(jù)的指針。

C++指針探討 (一)數(shù)據(jù)指針      沐楓網(wǎng)志
   
    1.  數(shù)據(jù)指針
     數(shù)據(jù)指針分為兩種:常規(guī)數(shù)據(jù)指針和成員數(shù)據(jù)指針
     
    1.1 常規(guī)數(shù)據(jù)指針
     這個不用說明了,和C語言一樣,定義、賦值是很簡單明了的。常見的有:int*, double* 等等。
     如:
     int value = 123;
     
int * pn = &value;
   
     
    1.2 成員數(shù)據(jù)指針
     有如下的結(jié)構(gòu):
     struct MyStruct
     {
       
int key;
       
int value;
     };
   
     現(xiàn)在有一個結(jié)構(gòu)對象:
     MyStruct me;
     MyStruct* pMe = &me;
   
     我們需要 value 成員的地址,我們可以:
     int * pValue = &me.value;
     //
     int * pValue = &pMe->value;
   
     當(dāng)然了,這個指針仍然是屬于第一種范籌----常規(guī)數(shù)據(jù)指針。
     
     好了,我們現(xiàn)在需要一種指針,它指向MyStruct中的任一數(shù)據(jù)成員,那么它應(yīng)該是這樣的子:
     int MyStruct::* pMV = &MyStruct::value;
     
//
     int MyStruct::* pMK = &MyStruct::key;
   
     這種指針的用途是用于取得結(jié)構(gòu)成員在結(jié)構(gòu)內(nèi)的地址。我們可以通過該指針來訪問成員數(shù)據(jù):
     int value = pMe->*pMV; // 取得pMe的value成員數(shù)據(jù)。
     int key = me.*pMK; // 取得me的key成員數(shù)據(jù)。
   
     那么,在什么場合下會使用到成員數(shù)據(jù)指針呢?
     確實,成員指針本來就不是一種很常用的指針。不過,在某些時候還是很有用處的。我們先來看看下面的一個函數(shù):
  int sum(MyStruct* objs, int MyStruct::* pm, int count)
  {
      
int result = 0;
      
for(int i = 0; i < count; ++i)
          result 
+= objs[i].*pm;
      
return result;
  }
     
     這個函數(shù)的功能是什么,你能看明白嗎?它的功能就是,給定count個MyStruct結(jié)構(gòu)的指針,計算出給定成員數(shù)據(jù)的總和。有點拗口對吧?看看下面的程序,你也許就明白了:
     
     MyStruct me[10=
     {
      {
1,2},{3,4},{5,6},{7,8},{9,10},{11,12},{13,14},{15,16},{17,18},{19,20}
     };
     
     
int sum_value = sum(me, &MyStruct::value, 10);
     
//計算10個MyStruct結(jié)構(gòu)的value成員的總和: sum_value 值 為 110     (2+4+6+8++20)
     
     
int sum_key = sum(me, &MyStruct::key, 10);
     
//計算10個MyStruct結(jié)構(gòu)的key成員的總和:   sum_key 值 為 100       (1+3+5+7++19)
   
     
     也許,你覺得用常規(guī)指針也可以做到,而且更易懂。Ok,沒問題:
     int sum(MyStruct* objs, int count)
     {
      
int result = 0;
      
for(int i = 0; i < count; ++i)
       result 
+= objs[i].value;
      
return result;
     }

     你是想這么做嗎?但這么做,你只能計算value,如果要算key的話,你要多寫一個函數(shù)。有多少個成員需要計算的話,你就要寫多少個函數(shù),多麻煩啊。

posted @ 2006-03-14 16:43 Beginning to 編程 閱讀(183) | 評論 (0)編輯 收藏

C++指針探討 (三) 成員函數(shù)指針 /zhuan

C語言的指針相當(dāng)?shù)撵`活方便,但也相當(dāng)容易出錯。許多C語言初學(xué)者,甚至C語言老鳥都很容易栽倒在C語言的指針下。但不可否認的是,指針在C語言中的位置極其重要,也許可以偏激一點的來說:沒有指針的C程序不是真正的C程序。
  然而C++的指針卻常常給我一種束手束腳的感覺。C++比C語言有更嚴格的靜態(tài)類型,更加強調(diào)類型安全,強調(diào)編譯時檢查。因此,對于C語言中最容易錯用的指針,更是不能放過:C++的指針被分成數(shù)據(jù)指針,數(shù)據(jù)成員指針,函數(shù)指針,成員函數(shù)指針,而且不能隨便相互轉(zhuǎn)換。而且這些指針的聲明格式都不一樣:

數(shù)據(jù)指針 T *
成員數(shù)據(jù)指針 T::*
函數(shù)指針 R (*)(...)
成員函數(shù)指針 R (T::*)(...)

  盡管C++中仍然有萬能指針void*,但它卻屬于被批斗的對象,而且再也不能“萬能”了。它不能轉(zhuǎn)換成成員指針。

  這樣一來,C++的指針就變得很尷尬:我們需要一種指針能夠指向同一類型的數(shù)據(jù),不管這個數(shù)據(jù)是普通數(shù)據(jù),還是成員數(shù)據(jù);我們更需要一種指針能夠指向同一類型的函數(shù),不管這個函數(shù)是靜態(tài)函數(shù),還是成員函數(shù)。但是沒有,至少從現(xiàn)在的C++標準中,還沒有看到。
 
沐楓網(wǎng)志 C++指針探討(三)成員函數(shù)指針

  自從有了類,我們開始按照 數(shù)據(jù)+操作 的方式來組織數(shù)據(jù)結(jié)構(gòu);自從有了模板,我們又開始把 數(shù)據(jù) 和 算法 分離,以便重用,實在夠折騰人的。但不管怎么折騰,現(xiàn)在大多數(shù)函數(shù)都不再單身,都嫁給了類,進了圍城。可是我們?nèi)匀恍枰軌蜃杂烧{(diào)用這些成員函數(shù)。
  考慮一下windows下的定時調(diào)用。SetTimer函數(shù)的原型是這樣的:

UINT_PTR SetTimer(
    HWND hWnd,
    UINT_PTR nIDEvent,
    UINT uElapse,
    TIMERPROC lpTimerFunc
);
  其中,參數(shù)就不解釋了,這個函數(shù)估計大多數(shù)windows開發(fā)人員都知道。lpTimerFunc是個會被定時調(diào)用的函數(shù)指針。假如我們不通過WM_TIMER消息來觸發(fā)定時器,而是通過lpTimerFunc來定時工作,那么我們就只能使用普通函數(shù)或靜態(tài)函數(shù),而無論如何都不能使用成員函數(shù),哪怕通過靜態(tài)函數(shù)轉(zhuǎn)調(diào)也不行。

  再考慮一下線程的創(chuàng)建:
uintptr_t _beginthread( 
   
void*start_address )( void * ),
   unsigned stack_size,
   
void *arglist 
);
  start_address仍然只支持普通函數(shù)。不過這回好了,它允許回調(diào)函數(shù)一個void*參數(shù),它將會arglist作為參數(shù)來調(diào)用start_address。于是,聰明的C++程序員,就利用arglist傳遞this指針,從而利用靜態(tài)函數(shù)成功的調(diào)用到了成員函數(shù)了:
class mythread
{
  
public:
    
static void doit(void* pThis)
    
{
    ((mythread*)pThis)
->doit();
    }

    
void doit(){}
}
;

main()
{
  
  mythread
* pmt = new mythread;
  _beginthread(
&mythread::doit, 0, (void*)pmt);
  
}

  但是顯然,C++程序員肯定不會因此而滿足。這里頭有許多被C++批判的不安定因素。它使用了C++中被認為不安全的類型轉(zhuǎn)換,不安全的void*指針,等等等等。但這是系統(tǒng)為C語言留下的調(diào)用接口,這也就認了。那么假如,我們就在C++程序中如何來調(diào)用成員函數(shù)指針呢?
  如下例,我們打算對vector中的所有類調(diào)用其指定的成員函數(shù):

#include <vector>
#include 
<algorithm>
#include 
<functional>
#include 
<iostream>
using namespace std;

class A
{
    
int value;
public:
    A(
int v){value = v;}
    
void doit(){ cout << value << endl;};
    
static void call_doit(A& rThis)
    
{
        rThis.doit();
    }

}
;


int main()
{
    vector
<A> va;
    va.push_back(A(
1));
    va.push_back(A(
2));
    va.push_back(A(
3));
    va.push_back(A(
4));
    
//方法1:
    
//for_each(va.begin(), va.end(), &A::doit); //error
    
//方法2:
    for_each(va.begin(), va.end(), &A::call_doit);
    
//方法3:
    for_each(va.begin(), va.end(), mem_fun_ref<void, A>(&A::doit));

    system(
"Pause");

    
return 0;
}

  方法1,編譯不能通過。for_each只允許具有一個參數(shù)的函數(shù)指針或函數(shù)對象,哪怕A::doit默認有一個this指針參數(shù)也不行。不是for_each沒考慮到這一點,而是根本做不到!
  方法2,顯然是受到了beginthread的啟發(fā),使用一個靜態(tài)函數(shù)來轉(zhuǎn)調(diào)用,哈哈成功了。但是不爽!這不是C++。
  方法3,呼,好不容易啊,終于用mem_fun_ref包裝成功了成員函數(shù)指針。
  似乎方法3不錯,又是類型安全的,又可以通用--慢著,首先,它很丑,哪有調(diào)用普通C函數(shù)指針那么漂亮啊(見方法2),用了一大串包裝,又是尖括號又是圓括號,還少不了&號!其次,它只能包裝不超過一個參數(shù)的函數(shù)!盡管它在for_each中夠用了,但是你要是想用在超過一個參數(shù)的場合,那只有一句話:不可能的任務(wù)。

  是的,在標準C++中,這是不可能的任務(wù)。但事情并不總是悲觀的,至少有許多第三方庫提供了超越mem_fun的包裝。如boost::function等等。但是它也有限制:它所支持的參數(shù)仍然是有限的,只有十多個,盡管夠你用的了;同樣,它也是丑陋的,永遠不要想它能夠簡單的用&來搞定。

  也許,以失去美麗的代價,來換取質(zhì)量上的保證,這也是C++對于函數(shù)指針的一種無奈吧……

  期待C++0x版本。它通過可變模板參數(shù),能夠讓mem_fun的參數(shù)達到無限個……

--------
   BTW: C++Builder擴展了一個關(guān)鍵字 closure ,允許成員函數(shù)指針如同普通函數(shù)指針一樣使用。也許C++0x能考慮一下……

posted @ 2006-03-14 16:42 Beginning to 編程 閱讀(354) | 評論 (0)編輯 收藏

一些基本的GDI操作BITMAP的方法 /zhuan

     摘要: 1  2 #ifndef _BITMAP_H 3 #define _BITMAP_H 4  5 #include <windows.h> 6  7 void SaveImage(const char ...  閱讀全文

posted @ 2006-03-10 11:27 Beginning to 編程 閱讀(1443) | 評論 (0)編輯 收藏

僅列出標題
共3頁: 1 2 3 

導(dǎo)航

統(tǒng)計

常用鏈接

留言簿(4)

隨筆分類

隨筆檔案

文章檔案

相冊

BlogDev

搜索

最新評論

閱讀排行榜

評論排行榜

青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品
  • <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精品二区三区| 免费一级欧美在线大片| 欧美日韩亚洲国产一区| 国产精品蜜臀在线观看| 国产日韩一区| 亚洲精品一区二区三区婷婷月| 99re6热只有精品免费观看| 亚洲主播在线观看| 久久久精品2019中文字幕神马| 美女免费视频一区| 91久久在线| 亚洲一级网站| 久久一二三国产| 欧美无乱码久久久免费午夜一区| 国产精品视频xxxx| 在线日韩av片| 翔田千里一区二区| 亚洲国产女人aaa毛片在线| 亚洲一品av免费观看| 免费成人美女女| 国产欧美精品在线| 亚洲欧洲精品一区二区| 欧美在线一级va免费观看| 亚洲国产欧美在线人成| 西瓜成人精品人成网站| 欧美人与性动交a欧美精品| 国产伊人精品| 午夜精品一区二区三区在线视| 欧美大尺度在线| 亚洲欧美在线一区| 欧美日韩一区二区三区在线| 在线免费观看视频一区| 性久久久久久久| 一区二区激情| 欧美精品偷拍| 在线观看视频一区二区欧美日韩| 亚洲性色视频| 日韩午夜在线视频| 欧美精品aa| 亚洲另类在线视频| 欧美岛国在线观看| 久久久久久尹人网香蕉| 国产日韩免费| 久久国产精品久久久久久久久久 | 国产精品sm| 亚洲精品国产精品国自产在线| 欧美诱惑福利视频| 亚洲一区免费视频| 欧美性大战久久久久久久| 日韩视频在线一区| 亚洲激情在线播放| 欧美—级a级欧美特级ar全黄| …久久精品99久久香蕉国产| 久久免费视频在线观看| 欧美一区二视频| 国产一区二区中文| 久久久久久穴| 久久噜噜亚洲综合| 一区一区视频| 亚洲激情影视| 欧美日韩综合久久| 亚洲欧美怡红院| 午夜欧美电影在线观看| 国产亚洲亚洲| 麻豆精品网站| 另类天堂av| 一区二区三区av| 亚洲性av在线| 国自产拍偷拍福利精品免费一| 久久天天躁狠狠躁夜夜爽蜜月| 久久精品国产综合| 亚洲日韩成人| 欧美freesex8一10精品| 久久精品国产99精品国产亚洲性色| 精品成人免费| 久久综合久久综合这里只有精品| 久久久久久久久久久久久女国产乱| 激情综合亚洲| 亚洲人成人一区二区三区| 欧美日韩一区二区欧美激情| 午夜国产精品视频| 久久香蕉国产线看观看av| 亚洲毛片一区二区| 亚洲一区欧美一区| 亚洲黄色有码视频| 亚洲一区二区在线观看视频| 伊人成人开心激情综合网| 亚洲人成网在线播放| 国产视频不卡| 亚洲国产精品久久久久婷婷老年| 国产精品成人一区| 久久精品一本| 欧美日韩视频免费播放| 久久久久久成人| 欧美另类变人与禽xxxxx| 欧美中文字幕第一页| 欧美va天堂va视频va在线| 亚洲综合清纯丝袜自拍| 蜜桃久久av一区| 亚洲欧美日韩成人| 牛牛精品成人免费视频| 久久久久久91香蕉国产| 欧美视频一二三区| 亚洲大片免费看| 国产视频亚洲| 久久躁日日躁aaaaxxxx| 99精品视频免费在线观看| 亚洲一区三区电影在线观看| 最新精品在线| 久久久久久久999| 欧美在线观看视频在线| 国产精品ⅴa在线观看h| 欧美激情网友自拍| 国产亚洲精品aa午夜观看| 日韩一区二区久久| 亚洲精品一区二区三区樱花| 欧美在线一二三四区| 欧美一区二区三区男人的天堂| 欧美日韩高清一区| 亚洲国产精品ⅴa在线观看| 韩日视频一区| 欧美伊久线香蕉线新在线| 亚洲欧美区自拍先锋| 欧美日韩成人综合| 亚洲区一区二| 亚洲久久成人| 欧美激情女人20p| 亚洲国产精品成人精品| 亚洲国产精品成人va在线观看| 久久精品一区二区国产| 久久久国产一区二区三区| 国产精品欧美经典| 亚洲永久在线观看| 欧美一级视频免费在线观看| 国产精品久久久久久久久久三级| 夜夜嗨av色综合久久久综合网| 一区二区冒白浆视频| 欧美午夜激情视频| 亚洲一区精品视频| 久久精品官网| 亚洲高清视频一区二区| 欧美黄污视频| 日韩一区二区电影网| 午夜视频在线观看一区二区三区| 国产女人aaa级久久久级| 欧美影院在线播放| 欧美va亚洲va国产综合| 亚洲精品一区二区三区樱花| 欧美老女人xx| 亚洲一区二区免费视频| 久久久www成人免费精品| 在线看视频不卡| 欧美国产一区在线| 宅男精品视频| 免费看av成人| 在线亚洲欧美视频| 国产一区二区久久| 欧美紧缚bdsm在线视频| 亚洲主播在线观看| 欧美第十八页| 性色av一区二区三区红粉影视| 激情懂色av一区av二区av| 欧美激情区在线播放| 亚洲你懂的在线视频| 亚洲国产高清自拍| 欧美影院在线播放| 最新日韩av| 国产一区二区欧美| 欧美人成免费网站| 久久久久久久欧美精品| 日韩一级精品| 欧美肥婆在线| 久久激情综合| 亚洲一级片在线观看| 亚洲第一区中文99精品| 国产精品伦理| 亚洲午夜一区| 国产精品视频99| 免费观看成人鲁鲁鲁鲁鲁视频| 妖精视频成人观看www| 美女视频黄a大片欧美| 亚洲综合色自拍一区| 亚洲福利精品| 国产亚洲美州欧州综合国| 欧美日韩高清在线观看| 久久亚洲国产成人| 亚洲午夜在线观看| 亚洲破处大片| 欧美国产日韩一区| 美女视频一区免费观看| 午夜精品一区二区三区在线| 亚洲精品欧洲精品| 亚洲国产高潮在线观看| 国产手机视频一区二区| 国产精品99免视看9|