• <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>

            UNICODE與ANSI的區(qū)別 (轉(zhuǎn))

                    什么是ANSI,什么又是UNICODE呢?其實(shí)這是兩種不同的編碼方式標(biāo)準(zhǔn),ANSI中的字符采用8bit,而UNICODE中的字符采用16bit。(對(duì)于字符來(lái)說(shuō)ANSI以單字節(jié)存放英文字符,以雙字節(jié)存放中文等字符,而Unicode下,英文和中文的字符都以雙字節(jié)存放)Unicode碼也是一種國(guó)際標(biāo)準(zhǔn)編碼,采用二個(gè)字節(jié)編碼,與ANSI碼不兼容。目前,在網(wǎng)絡(luò)、Windows系統(tǒng)和很多大型軟件中得到應(yīng)用。8bit的ANSI編碼只能表示256種字符,表示26個(gè)英文字母是綽綽有余的,但是表示漢字,韓國(guó)語(yǔ)等有著成千上萬(wàn)個(gè)字符的非西方字符肯定就不夠了,正是如此才引入了UNICODE標(biāo)準(zhǔn)。   
                 在軟件開發(fā)中,特別是使用C語(yǔ)言的一些有關(guān)字符串處理的函數(shù),ANSI和UNICODE是區(qū)分是用的,那么ANSI類型的字符和UNICODE類型的字符如何定義,如何使用呢?ANSI和UNICODE又如何轉(zhuǎn)換呢?   
               一.定義部分:  
               ANSI:char    str[1024]; 可用字符串處理函數(shù):strcpy( ),    strcat( ),   strlen( )等等。
            UNICODE:wchar_t    str[1024];可用字符串處理函數(shù)   
            二.可用函數(shù): 
               ANSI:即char,可用字符串處理函數(shù):strcat(    ),strcpy(    ),    strlen(    )等以str打頭的函數(shù)。   
               UNICODE:即wchar_t 可用字符串處理函數(shù):wcscat(),wcscpy(),wcslen()等以wcs打頭的函數(shù)。   
               三.系統(tǒng)支持  
                  Windows    98    :只支持ANSI。   
                  Windows    2k    :既支持ANSI又支持UNICODE。   
                  Windows    CE    :只支持UNICODE。   
                  說(shuō)明   
                  1 在COM里面只支持UNICODE。   
                  2.Windows   2000整個(gè)OS系統(tǒng)都是基于UNICODE的,為此在windows 2000 下使用ANSI是需要付出代價(jià)的,雖然在編碼上不用任何的轉(zhuǎn)換,但是這種轉(zhuǎn)化是隱藏的,是占用系統(tǒng)資源的(CPU,內(nèi)存)。   
                  3 在Windows 98下必須使用UNICODE,則需要自己手動(dòng)的編碼切換。   
                四.如何區(qū)分:   
                在我們軟件開發(fā)中往往需要即支持ANSI又支持UNICODE,不可能在要求類型轉(zhuǎn)換的時(shí)候,重新改變字符串的類型,和使用于字符串上的操作函數(shù)。為此, 標(biāo)準(zhǔn)C運(yùn)行期庫(kù)和Windows 提供了宏定義的方式。   
                在C語(yǔ)言里面提供了 _UNICODE宏(有下劃線),在Windows里面提供了UNICODE宏(無(wú)下劃線),只要定了_UNICODE宏和UNICODE宏,系統(tǒng)就會(huì)自動(dòng)切換到UNICODE版本,否則,系統(tǒng)按照ANSI的方式進(jìn)行編譯和運(yùn)行。   
                只定義了宏并不能實(shí)現(xiàn)自動(dòng)的轉(zhuǎn)換,他還需要一系列的字符定義支持。   
               1. TCHAR   
               如果定義了UNICODE宏則TCHAR被定義為wchar_t。   
                typedef    wchar_t    TCHAR;   
                否則TCHAR被定義為char   
                typedef    char   TCHAR;   
               2.LPTSTR   
            如果定義了UNICODE宏則LPTSTR被定義為L(zhǎng)PWSTR。(以前一直不知道LPWSTR是什么東東,終于明白了)   
               typedef    LPTSTR   LPWSTR;   
               否則TCHAR被定義為char   
               typedef    LPTSTR   LPSTR;  
            補(bǔ)充一下:
            UTF-8是可以用于真正的流式傳輸?shù)模琔nicode是一種編碼方案   
                我的理解是UTF-8是Unicode的一種具體實(shí)現(xiàn)。類似的實(shí)現(xiàn)還有UTF-16等等。


            ANSI/Unicode字符和字符串 
            TChar.h是String.h的修改,用于創(chuàng)建ANSI/Unicode通用字符串。

            Unicode字符串的每個(gè)字符都是16位的。

            Win9x只支持ANSI;Win2000/XP/2003支持ANSI/Unicode;WinCE只支持Unicode
                   附:有部分Unicode函數(shù)也可以在Win9X中使用,但可能會(huì)出現(xiàn)意想不到錯(cuò)誤。

            wchar_t是Unicode字符的數(shù)據(jù)類型。

            所有的Unicode函數(shù)均以wcs開頭,ANSI函數(shù)均以str開頭;ANSI C規(guī)定C運(yùn)行期庫(kù)支持ANSI和Unicode
                                             ANSI                                                                              Unicode
                   char   *strcat(char   *,   const   char   *)                           wchar_t   *wcscat(wchar_t   *,   const   wchar_t   *) 
                   char   *strchr(const   char * , int)                                   wchar_t    *wcschr(const   wchar_t   * , int) 
                   int   strcmp(const   char   *,    const   char   *)                int    wcscmp(const   wchar_t   *, const   wchar_t *)
                   char *strcpy(char   *,   const   char   *)                           wchar_t   *wcscpy(wchar_t    *,   const   wchar_t    *)
                   size_t   strlen(const   char   *)                                        wchar_t    wcslen(const   wchar_t   *)

            L" wash " : 用于將ANSI字符串轉(zhuǎn)換為Unicode字符串;
                    _TEXT(" wash ")根據(jù)是否定義Unicode或_Unicode進(jìn)行轉(zhuǎn)換。
                   附:_Unicode用于C運(yùn)行庫(kù);Unicode用于Windows頭文件。

            ANSI/Unicode通用數(shù)據(jù)類型
                                    Both(ANSI/Unicode)                    ANSI                       Unicode
                                           LPCTSTR                                 LPCSTR                   LPCWSTR
                                           LPTSTR                                    LPSTR                      LPWSTR
                                           PCTSTR                                   PCSTR                      PCWSTR
                                           PTSTR                                      PSTR                         PWSTR
                                           TBYTE(TCHAR)                      CHAR                         WCHAR

            在設(shè)計(jì)dll時(shí)最好提供ANSI和Unicode函數(shù),ANSI函數(shù)只用于分配內(nèi)存,將字符轉(zhuǎn)換為Unicode字符,然后調(diào)用Unicode函數(shù)。

            最好使用操作系統(tǒng)函數(shù),少使用或不實(shí)用C運(yùn)行期函數(shù)
                    eg:操作系統(tǒng)字符串函數(shù)(shlWApi.h)
                            StrCat(), StrChr(), StrCmp(), StrCpy()等
                            注意它們區(qū)分大小寫,也區(qū)分ANSI和Unicode版本
                    附:ANSI版函數(shù)在原函數(shù)后加大寫字母A
                            Unicode函數(shù)在原函數(shù)后加大寫字母W

            成為符合ANSI和Unicode的函數(shù)
                    ? 將文本串視為字符數(shù)組,而不是c h a r s數(shù)組或字節(jié)數(shù)組。
                    ? 將通用數(shù)據(jù)類型(如T C H A R和P T S T R)用于文本字符和字符串。
                    ? 將顯式數(shù)據(jù)類型(如B Y T E和P B Y T E)用于字節(jié)、字節(jié)指針和數(shù)據(jù)緩存。
                    ? 將T E X T宏用于原義字符和字符串。
                    ? 修改字符串運(yùn)算問(wèn)題 。
                      如:sizeof(szBuffer) -> sizeof(szBuffer) / sizeof(TCHAR)
                              malloc(charNum) -> malloc(charNum * sizeof(TCHAR))   

            對(duì)Unicode字符操作的函數(shù)還有:(也有ANSI和Unicode版本)
                   lstrcat() , lstrcmp() / lstrcmpi()[ 它們?cè)趦?nèi)部調(diào)用CompareString() ], lstrcpy(), lstrlen()
                   這些是作為宏實(shí)現(xiàn)的。

                      C運(yùn)行期函數(shù)                                       windows函數(shù)
                              tolower()                                  PTSTR   CharLower(PTSTR   pszString)
                              toupper()                                 PTSTR   CharUpper(PTSTR   pszString)
                              isalpha()                                  BOOL   IsCharAlpha(TCHAR   ch)
                                                                               BOOL   ISCharAlphaNumeric(TCHAR   ch)
                              islower()                                  BOOL   IsCharLower(TCHAR   ch)
                              isupper()                                 BOOL   IsCharUpper(TCHAR   ch)
                              print()                                       wsprintf()
                   轉(zhuǎn)換Buffer:DWORD   CharLowerBuffer(PTSTR   pszString , DWORD cchString)
                                          DWORD CharUpperBuffer(PTSTR   pszString , DWORD   cchString)
                   也可轉(zhuǎn)換單個(gè)字符,如:TCHAR   cLowerCaseChar = CharLower((PTSTR)szString[0])

            確定字符是ANSI或Unicode
                    BOOL   IsTextUnicode(
                                 const   VOID   * pBuffer,   //input   buffer   to be   examined
                                 int   cb,                               //size of input   buffer
                                 LPINT   lpi                         //options
                    )
                   附:此函數(shù)在Win9x系統(tǒng)中,沒有實(shí)現(xiàn)代碼,始終返回FALSE

            Unicode與ANSI之間的轉(zhuǎn)換
                    char   szA[40];
                    wchar   szW[40];
                    // Normal   sprintf : all   string   are   ANSI
                    sprintf( szA , " %s " , " ANSI   str ");
                    // Convert   Unicode   string   to ANSI
                    sprintf(   szA,   " %S " ,   L" Unicode   str ");
                    // Normal   swprintf : all string are unicode
                    swprinf( szW , "%s" , L" Unicode   str ");
                    // Convert   ANSI   String to Unicode
                    swprinf( szW, L"%S" , "ANSI str");

                    int   MultiByteToWideChar(
                          UINT   uCodePage,                   //code page,   0
                          DWORD   dwFlags,                   //character-type   options,   0
                          PCSTR   pMultiByte,                  //source   string   Addr
                          int   cchMultiByte,                       //source   string   byte length
                          PWSTR   pWideCharStr,          //Dest string   Addr
                          int   cchWideChar                      //Dest   string char   Nums
                     )
                    u C o d e P a g e參數(shù)用于標(biāo)識(shí)一個(gè)與多字節(jié)字符串相關(guān)的代碼頁(yè)號(hào)。d w F l a g s參數(shù)用于設(shè)定另一個(gè)控件,它可以用重音符號(hào)之類的區(qū)分標(biāo)記來(lái)影響字符。這些標(biāo)志通常并不使用,在d w F l a g s參數(shù)中傳遞0。p M u l t i B y t e S t r參數(shù)用于設(shè)定要轉(zhuǎn)換的字符串, c c h M u l t i B y t e參數(shù)用于指明該字符串的長(zhǎng)度(按字節(jié)計(jì)算)。如果為c c h M u l t i B y t e參數(shù)傳遞- 1,那么該函數(shù)用于確定源字符串的長(zhǎng)度。轉(zhuǎn)換后產(chǎn)生的U n i c o d e版本字符串將被寫入內(nèi)存中的緩存,其地址由p Wi d e C h a r S t r參數(shù)指定。必須在c c h Wi d e C h a r參數(shù)中設(shè)定該緩存的最大值(以字符為計(jì)量單位)。如果調(diào)用M u l t i B y t e To Wi d e C h a r,給c c h Wi d e C h a r參數(shù)傳遞0,那么該參數(shù)將不執(zhí)行字符串的轉(zhuǎn)換,而是返回為使轉(zhuǎn)換取得成功所需要的緩存的值。

                 可以通過(guò)下列步驟將多字節(jié)字符串轉(zhuǎn)換成U n i c o d e等價(jià)字符串:
                 1) 調(diào)用M u l t i B y t e To Wi d e C h a r函數(shù),為p Wi d e C h a r S t r參數(shù)傳遞N U L L,為c c h Wi d e C h a r參數(shù)傳遞0。
                 2) 分配足夠的內(nèi)存塊,用于存放轉(zhuǎn)換后的U n i c o d e字符串。該內(nèi)存塊的大小由前面對(duì)M u l t B y t e To Wi d e C h a r的調(diào)用返回。
                 3) 再次調(diào)用M u l t i B y t e To Wi d e C h a r,這次將緩存的地址作為p Wi d e C h a r S t r參數(shù)來(lái)傳遞,并傳遞第一次調(diào)用M u l t i B y t e To Wi d e C h a r時(shí)返回的緩存大小,作為c c h Wi d e c h a r參數(shù)。
                 4) 使用轉(zhuǎn)換后的字符串。
                 5) 釋放U n i c o d e字符串占用的內(nèi)存塊。

                int WideCharToMultiByte(
                      UINT CodePage,                        // code page
                      DWORD dwFlags,                      // performance and mapping flags
                      LPCWSTR lpWideCharStr,      // wide-character string
                      int cchWideChar,                       // number of chars in string
                      LPSTR lpMultiByteStr,               // buffer for new string
                      int cbMultiByte,                           // size of buffer
                      LPCSTR lpDefaultChar,            // default for unmappable chars
                      LPBOOL lpUsedDefaultChar   // set when default char used
                 )

             

            本文轉(zhuǎn)自:http://hi.baidu.com/%C6%DF%D4%C2%BA%A3%C0%B6/blog/item/65639b25cc31f16234a80fc4.html

            posted @ 2011-09-07 16:21 Daywei 閱讀(838) | 評(píng)論 (0)編輯 收藏

            C+之父力作學(xué)習(xí)筆記6——派生類

                  現(xiàn)在來(lái)考慮做一個(gè)程序,處理某公司所雇傭人員的問(wèn)題。這個(gè)程序可能包含如下一種數(shù)據(jù)結(jié)構(gòu):
            struct Employee
            {
                
            string first_name,family_name;
                
            char middle_initial;
                Date hiring_date;
                
            short department;
                
            //
            }
            ;
            下一步我們可能需要去定義經(jīng)理:
            struct Manager
            {
                Employee emp;
                list
            <Employee*> group; //所管理的人員
                short level;
                
            //
            }
            ;
            一個(gè)經(jīng)理同時(shí)也是一個(gè)雇員,所以在Manager對(duì)象的emp成員存儲(chǔ)著Employee數(shù)據(jù)。很明顯這樣的設(shè)計(jì)是糟糕的,大家都會(huì)想到派生:
            struct Manager:public Employee
            {
                list
            <Employee*> group;
                
            short level;
            }
            ;
            這個(gè)Manager是由Employee派生的,反過(guò)來(lái)就是說(shuō),Employee是Manager的一個(gè)基類。類Manager包含類Employee得所有成員,再加上它自己的一些成員。
                  按照這種方式從Employee派生出Manager,就使Manager成為Employee的一個(gè)子類型,使Manager可以用在能夠接受Employee的任何地方。因?yàn)镸anager是Employee,所以Manager*就可以當(dāng)做Employee*使用。然而,因?yàn)镋mployee不一定是Manager,所以Employee*就不能當(dāng)做Manager*用。總而言之類Derived有一個(gè)公用基類Base,那么就可以用Derived*給Base*類型的變量賦值,不需要顯示的類型轉(zhuǎn)換。而相反的方向,從Base*到Derived*則必須顯示轉(zhuǎn)換。例如:
            void g(Manager mm,Employee ee)
            {
                Employee
            * pe = &mm;  //可以:Manager都是Employee
                Manager* pm = &ee;   //錯(cuò)誤:Employee不一定是Manager
                pm->level = 2;       //災(zāi)難:ee沒有l(wèi)evel
                pm = static_cast<Manager*>(pe);//蠻力:這個(gè)可以,因?yàn)閜e指向的是Manager mm
                pm->level = 2;       //沒問(wèn)題
            }

                  派生類的成員可以使用其基類的公用的和保護(hù)的成員,但是,派生類不能使用基類的私有成員。對(duì)于派生類的成年公園而言,保護(hù)成員就像是公用成員;但對(duì)于其他函數(shù)它們則像是私用成員。
                  下面說(shuō)說(shuō)派生類的構(gòu)造函數(shù)和析構(gòu)函數(shù)
                  有些派生類需要構(gòu)造函數(shù)。如果某個(gè)基類中有構(gòu)造函數(shù),那么就必須調(diào)用這些構(gòu)造函數(shù)中的某一個(gè)。默認(rèn)構(gòu)造函數(shù)可以被隱含的調(diào)用,但是,如果一個(gè)基類的所有構(gòu)造函數(shù)都有參數(shù),那么就必須顯示的調(diào)用其中的某一個(gè)。基類構(gòu)造函數(shù)的參數(shù)應(yīng)在派生類構(gòu)造函數(shù)的定義中有明確描述。在這方面,基類的行為恰恰就像是派生類的一個(gè)成員。例如:
            Employee::Employee(const string& n,int d):family(n),department(d)
            {
                
            //
            }


            Manager::Manager(
            const string& n,int d,int lvl):Employee(n,d),/*初始化基類*/level(lvl)/*初始化成員*/
            {
                
            //
            }
            派生類的構(gòu)造函數(shù)只能描述它自己的成員和自己的直接基類的初始式,它不能直接去初始化基類的成員,例如:
            Manager::Manager(const string& n,int d,int lvl):family_name(n).department(d),level(lvl)//錯(cuò)誤:在Manager里沒有family_name和department的聲明
            {
            //
            }
             類對(duì)象的構(gòu)造是自下而上進(jìn)行的:首先是基類,而后是成員,再后才是派生類本身。類對(duì)象的銷毀則正好以相反的順序進(jìn)行:首先是派生類本身,而后是成員,再后才是基類。
                  對(duì)于給定的一個(gè)類型為Base*的指針,被指的對(duì)象到底屬于哪個(gè)派生類型呢?這個(gè)問(wèn)題有四種基本的解決方案:
            1.  保證被指的只能是唯一類型的對(duì)象
            2. 在基類里安排一個(gè)類型域,供函數(shù)檢查
            3.  使用dynamic_cast
            4.  使用虛函數(shù)  

                   從Employee的函數(shù)中取得“正確的”行為i,而又不依賴于實(shí)際使用的到底是哪一種Employee,這就是所謂的多態(tài)性。一個(gè)帶有虛函數(shù)的類型被稱為是一個(gè)多態(tài)類型。要在C++里取得多態(tài)行為,被調(diào)用的函數(shù)就必須是虛函數(shù),而對(duì)象則必須是通過(guò)指針或者引用去操作的。如果直接操作一個(gè)對(duì)象(而不是通過(guò)指針或引用),它的確切類型就已經(jīng)為編譯器所知,因此也就不需要運(yùn)行時(shí)的多態(tài)性了。
                  那么一個(gè)虛函數(shù)聲明為純虛函數(shù),則這個(gè)虛函數(shù)所在的類為抽象類。用=0作為初始式就使虛函數(shù)成為“純虛的”。注意:不能創(chuàng)建抽象類的對(duì)象。抽象類只能做界面,作為其他類的基類。還有一點(diǎn)也要指的注意,一個(gè)未在派生類里定義的純虛函數(shù)仍舊還是一個(gè)純虛函數(shù),這種情況也將使該派生類仍為一個(gè)抽象類。例如:

            class Shape
            {
                 
            public:
                    
            virtual void draw()=0;
                    
            virtual bool isClose()=0;
                 
            //
            }
            ;

            class Circel:public Shape
            {
                
            public:
                   
            bool isClose(){return true;}//覆蓋Shap::isClose
                   
            //draw尚未覆蓋
            }
            ;

            Circel a;//錯(cuò)誤:聲明的是抽象類Circel對(duì)象

            抽象類的最重要用途就使提供一個(gè)界面,而又不是暴露任何實(shí)現(xiàn)的細(xì)節(jié)。
                  
                 忠告 :

            • 避免類型域
            • 用抽象類將設(shè)計(jì)的中心集中到提供清晰的界面方面
            • 用抽象類使界面最小化
            • 一個(gè)有虛函數(shù)的類應(yīng)該有一個(gè)虛析構(gòu)函數(shù)
            • 抽象類通常不需要構(gòu)造函數(shù)

            posted @ 2011-08-28 17:20 Daywei 閱讀(1982) | 評(píng)論 (0)編輯 收藏

            C++之父力作學(xué)習(xí)筆記5——運(yùn)算符重載

                  在C++包含很多運(yùn)算符,但以下幾個(gè)運(yùn)算符不能由用戶定義:
                  ::(作用域解析;)
                  ,(成員選擇)
                  .* (通過(guò)到成員的指針做成員選擇)
                  ?:三元條件運(yùn)算符
                  sizeof和typeid

                  運(yùn)算符函數(shù)的名字是由關(guān)鍵字operator后跟對(duì)應(yīng)的運(yùn)算符構(gòu)成的;例如operator<<。運(yùn)算符函數(shù)的定義和使用都可以像其他函數(shù)一樣。使用運(yùn)算符不過(guò)是顯示調(diào)用運(yùn)算符函數(shù)的一種簡(jiǎn)寫形式。例如
            void f(complex a,complex b)
            {
                complex c
            =a+b;  //簡(jiǎn)寫
                complex d=a.operator+(b);//顯示調(diào)用
            }


                  一個(gè)運(yùn)算符函數(shù)必須或者是一個(gè)成員函數(shù),或者至少有一個(gè)用戶定義類型的參數(shù)(重新定義運(yùn)算符new和delete的函數(shù)則沒有此項(xiàng)要求)。這一規(guī)則就保證了用戶不能改變?cè)斜磉_(dá)式的意義,除非表達(dá)式中包含有用戶定義類型的對(duì)象。特別的,不能定義只對(duì)指針進(jìn)行操作的運(yùn)算符函數(shù)。

                  忠告:
                  1.定義運(yùn)算符主要是為了模仿習(xí)慣使用方式
                  2.對(duì)于大型運(yùn)算對(duì)象,請(qǐng)使用const引用參數(shù)類型
                  3.對(duì)于需要訪問(wèn)表示的操作,優(yōu)先考慮作為成員函數(shù)而不是作為非成員函數(shù)
                  4.對(duì)于對(duì)稱的運(yùn)算符采用非成員函數(shù)
                  5.將只有一個(gè)“大小參數(shù)”的構(gòu)造函數(shù)做成explicit

                  運(yùn)算符重載的內(nèi)容應(yīng)該還是挺多的,但卻不知道如何寫,看來(lái)還是文筆太差了,有機(jī)會(huì)再補(bǔ)上吧。
                  

            posted @ 2011-08-20 13:41 Daywei 閱讀(1476) | 評(píng)論 (0)編輯 收藏

            C++之父力作學(xué)習(xí)筆記(4)——類的好多事

                  類,這個(gè)概念比較大。包含的事太多。咱們就一一的盡量弄清楚它。
                  一個(gè)類就是一個(gè)用戶定義類型。C++里類概念的目標(biāo)就是為程序員提供一種建立新類型的工具,是這些新類型的使用能夠像內(nèi)部一樣方便。
                  訪問(wèn)控制:class成員的默認(rèn)訪問(wèn)方式是私有的。一個(gè)struct也是一個(gè)class,但是其成員的默認(rèn)方式是公用的。非成員函數(shù)禁止訪問(wèn)私有成員。
                  構(gòu)造函數(shù):就是函數(shù)名和類名一樣的函數(shù)且沒有返回值。這誰(shuí)都知道。It's easy。而默認(rèn)構(gòu)造函數(shù)就是調(diào)用時(shí)不必提供參數(shù)的構(gòu)造函數(shù)。如果用戶自己聲明了一個(gè)默認(rèn)構(gòu)造函數(shù),那么就會(huì)去使用它;否則,如果有必要,而且用戶沒有聲明其他的構(gòu)造函數(shù),編譯器就會(huì)設(shè)法去生成一個(gè)。編譯器生成的默認(rèn)構(gòu)造函數(shù)將隱式地為類類型的成員和它的基類調(diào)用有關(guān)的默認(rèn)構(gòu)造函數(shù)。這里解釋一下:類類型(Class type)即指那些由程序員定義的類而產(chǎn)生的類型,以便與內(nèi)部類型和其他用戶定義類型相區(qū)分。相信大家這里也沒什么問(wèn)題。有一個(gè)注意點(diǎn)來(lái)了,由于const和引用必須進(jìn)行初始化,包含const或引用成員的類就不能進(jìn)行默認(rèn)構(gòu)造,除非程序員的我們自己顯示的提供默認(rèn)構(gòu)造函數(shù)。例如:
            struct X
            {
                
            const int a;
                
            const int& r;
            }
            ;
            X x;
            //錯(cuò)誤;X無(wú)默認(rèn)構(gòu)造函數(shù)
                  默認(rèn)構(gòu)造函數(shù)也可以顯示調(diào)用。內(nèi)部類型同樣也有默認(rèn)構(gòu)造函數(shù)。
                  下面再談?wù)剰?fù)制構(gòu)造函數(shù),先看看復(fù)制構(gòu)造函數(shù)是怎么引進(jìn)來(lái)的。
            按照默認(rèn)約定,類對(duì)象可以復(fù)制。特別是可以用一個(gè)類的對(duì)象和復(fù)制對(duì)該類的其他對(duì)象進(jìn)行初始化。即使是聲明了構(gòu)造函數(shù)的地方,也是可以這樣做:
            Date d=today;//通過(guò)復(fù)制初始化
            按照默認(rèn)方式,類對(duì)象的復(fù)制就是其中各個(gè)成員的復(fù)制。如果某個(gè)類X所需要的不是這種默認(rèn)方式,那么就可以定義一個(gè)復(fù)制構(gòu)造函數(shù)X::X(const X&),由它提供所需要的行為。還有一個(gè)概念就是復(fù)制賦值,很容易和復(fù)制構(gòu)造函數(shù)搞混。咱們就一起搞清楚它們。先看一段程序:
            void h()
            {
                Table t1;
                Table t2
            =t1;//復(fù)制初始化
                Table t3;
                t3
            =t2;      //復(fù)制賦值
            }
            看似好像沒什么問(wèn)題,對(duì)于復(fù)制上面提到的解釋方式,在應(yīng)用到具有指針成員的類的對(duì)象時(shí),就可能產(chǎn)生一種出人意料的作用。對(duì)于包含了由構(gòu)造函數(shù)/析構(gòu)函數(shù)管理的資源的對(duì)象而言,按成員復(fù)制的語(yǔ)義通常是不正確的。在這里,Table的默認(rèn)構(gòu)造函數(shù)為t1和t3各調(diào)用了一次,一共是兩次。然而Table的析構(gòu)函數(shù)則被調(diào)用了三次;對(duì)t1、t2和t3各一次!由于賦值的默認(rèn)解釋是按成員賦值,所以在h()結(jié)束時(shí),t1、t2和t3中將各包含一個(gè)指針,它們都指向建立t1時(shí)從自由存儲(chǔ)中分配的那個(gè)名字?jǐn)?shù)組。在建立t3時(shí)所分配的數(shù)組的指針并沒有保留下來(lái),因?yàn)樗毁x值t3=t2覆蓋掉了。這樣,如果沒有自動(dòng)廢料收集,對(duì)這個(gè)程序而言,該數(shù)組的存儲(chǔ)就將永遠(yuǎn)丟掉了。而在另一方面,為t1的創(chuàng)建而分配的數(shù)組因?yàn)橥瑫r(shí)出現(xiàn)在t1、t2和t3里,將被刪除3次。這種情況所導(dǎo)致的結(jié)果是無(wú)定義,很可能是災(zāi)難性的。這類反常情況可以避免,方式就是將Table復(fù)制的意義定義清楚:
            class Table
            {
                
            //---
                Table(const Table&);//復(fù)制構(gòu)造函數(shù)
                Table& operator=(const Table&);//復(fù)制賦值
            }
            ;
            咱們自己可以為這些復(fù)制操作定義自己認(rèn)為最合適的任何意義,例如
            //這里補(bǔ)上Table類的詳細(xì)定義
            class Table
            {
                Name
            * p;
                size_t sz;
            public:
                Table(size_t s
            =15)
                
            {
                    p
            =new Name[sz=s];
                }

                
            ~Table()
                

                    delete[] p;
                }

                Name
            * loopup(const char*);
                
            bool insert(Name*);
            }


            Table::Table(
            const Table& t)//復(fù)制構(gòu)造函數(shù)
            {
               p
            =new Name[z=t.sz];
               
            for(int i=0;i<sz;i++)
                  p[i]
            =t.p[i];
            }


            Table
            & Table::operator=(const Table& t)//賦值
            {
                
            if(this!=&t)//當(dāng)心自賦值:t=t
                
            {
                    delete[] p;
                    p
            =new Name[sz=t.sz];
                    
            for(int i=0;i<sz;i++)
                        p[i]
            =t.p[i];
                }

                
            return *this;
            }
            情況幾乎總是如此,復(fù)制構(gòu)造函數(shù)與復(fù)制賦值通常都很不一樣。究其根本原因,復(fù)制構(gòu)造函數(shù)是去完成對(duì)為初始化的存儲(chǔ)區(qū)的初始化,而復(fù)制賦值運(yùn)算符則必須正確處理一個(gè)結(jié)構(gòu)良好的對(duì)象。
                  成員常量:
                  對(duì)那些靜態(tài)整型成員,可以給它的成員聲明加上一個(gè)常量表達(dá)式作為初始式,例如
            class Curious
            {
                
            static const int c1=7;//ok,但要記得去定義
                static int c2=11;//錯(cuò)誤:非const
                const int c3;//錯(cuò)誤:非Static
                static const int c4=f(1);//錯(cuò)誤:在類里的初始表達(dá)式不是常量
                static const float c5=7.0;//錯(cuò)誤:在類里初始化的不是整型
            }
            1)在類中不能用const來(lái)創(chuàng)建常量!因?yàn)椋侯愔皇敲枋隽藢?duì)象的形式,并沒有真正創(chuàng)建對(duì)象!所以, 在對(duì)象建立之前,并沒有存值空間!
            2)而const是用來(lái)創(chuàng)建常量的!
            方法1 你可以用枚舉:
            class a
            {
            enum{buf_size_t buf_size=、、、}//用枚舉創(chuàng)建一個(gè)常量,但不是數(shù)據(jù)成員

            }

            方法2 你可以用static
            class a
            {
            private
              
            static const buf_size_t buf_size=30//該常量將與憋得靜態(tài)常量存儲(chǔ)在一起,而不是存儲(chǔ)在對(duì)象中
            }
            但《C++程序設(shè)計(jì)語(yǔ)言》書上說(shuō)當(dāng)你用到某個(gè)被初始化的成員,而且需要將它作為對(duì)象存入存儲(chǔ)器時(shí),這個(gè)成員就必須在某處有定義。初始式不必重復(fù)寫:
            const int Curious::c1;//必須,但這里不必重復(fù)初始式
            const int* p=&Cusious::c1;//ok:Curious::c1已經(jīng)有定義
            這里有點(diǎn)讓我懵了,為什么還要const int Curious::c1;//必須,但這里不必重復(fù)初始式 這一行呢?還說(shuō)是必須,經(jīng)過(guò)測(cè)試是有問(wèn)題的——當(dāng)前范圍內(nèi)的定義或重新聲明非法,到底是書錯(cuò)了還是還有其他什么原因?
            還請(qǐng)高手不吝賜教
            今天就到這里吧,到這里就出了問(wèn)題,還需要思考。

            這里有一篇博文關(guān)于
            VC6.0中,整型const static成員不能在類的定義體中初始化. http://blog.csdn.net/yiruirui0507/article/details/5984530




            posted @ 2011-08-05 17:00 Daywei 閱讀(2215) | 評(píng)論 (0)編輯 收藏

            C++之父力作學(xué)習(xí)筆記3——指針

               由于工作需要轉(zhuǎn)成了C#,好久沒有學(xué)C++了,之前學(xué)了一段時(shí)間的C++,也寫過(guò)兩篇,放在博客園里的,現(xiàn)在有專門的C++博客,以后就在這里寫了。以下是前兩篇的地址
            C++之父力作學(xué)習(xí)筆記1    C++之父力作學(xué)習(xí)筆記
                
               今天來(lái)簡(jiǎn)單說(shuō)一下指針,可以說(shuō)指針是一個(gè)難點(diǎn),是一把雙刃劍,也許高手才能運(yùn)用自如,像我這樣的菜鳥就會(huì)傷到自己。呵呵,廢話少說(shuō)。
               指針:對(duì)類型T,T*是“到T的指針”,也就是說(shuō),一個(gè)類型為T*的變量能保存一個(gè)類型T的對(duì)象的地址。例如:
            char c='a';
            char *p=&c;//p保存著c的地址

            用圖表示是:

            這些都挺容易理解的,不幸的是,到數(shù)組的指針和到函數(shù)的指針需要更復(fù)雜的記法:
            int* pi;          //到int的指針
            char** ppc;       //到字符的指針的指針
            int* ap[10];      //10個(gè)到int的指針的數(shù)組
            int (*fp)(char*); //到函數(shù)的指針,這種函數(shù)以char*為參數(shù),返回int
            int* f(char*);    //有一個(gè)char*參數(shù)的函數(shù),返回一個(gè)到ini的指針

               對(duì)指針的基本操作是間接引用,也就是說(shuō)引用被指針?biāo)傅哪莻€(gè)對(duì)象。這一操作也被稱作間接(indirectionn)。間接運(yùn)算符是(前綴的)一元*。例如
            char c='a';
            char* p=&c;   //p保存著c的地址
            char c2=*p;   //c2=='a'
            被p所指的變量是c,而c中所存的值是'a'。所以由*p賦給c2的值就是'a'.
            注意:這里解釋一下 間接運(yùn)算符是(前綴的)一元*。這就要扯到聲明的結(jié)構(gòu)了。
                     一個(gè)聲明由四個(gè)部分組成:一個(gè)可選的“描述符”,一個(gè)基礎(chǔ)類型,一個(gè)聲明符,還有一個(gè)可選的初始式。除了函數(shù)和名字空間之外,其他聲明都應(yīng)該由分號(hào)結(jié)束。例如:
            char* kings[]={"Antigonus","Seleucus","Ptolemy"};
            這里的基礎(chǔ)類型是char,聲明符是*kings[],而初始化是={...}。
                  描述符是一個(gè)開始關(guān)鍵字,例如:virtual和extern,它們說(shuō)明了被聲明事物的某些非類型的屬性。
                  聲明符由一個(gè)名字和可選的若干聲明運(yùn)算符組成。最常用的聲明運(yùn)算符是
                  *             指針          前綴
                  *const     常量指針     前綴
                  &            引用           前綴
                  []            數(shù)組          后綴
                  ()            函數(shù)          后綴




            posted @ 2011-07-26 11:13 Daywei 閱讀(2540) | 評(píng)論 (0)編輯 收藏

            僅列出標(biāo)題
            共4頁(yè): 1 2 3 4 
            <2025年5月>
            27282930123
            45678910
            11121314151617
            18192021222324
            25262728293031
            1234567

            導(dǎo)航

            統(tǒng)計(jì)

            常用鏈接

            留言簿

            隨筆分類

            隨筆檔案

            文章檔案

            牛人博客

            搜索

            積分與排名

            最新評(píng)論

            閱讀排行榜

            久久精品国产亚洲5555| 性高湖久久久久久久久AAAAA| 久久久精品2019免费观看| 午夜久久久久久禁播电影| 久久国产精品无码HDAV| 2020最新久久久视精品爱| 亚洲精品成人网久久久久久| 国产A级毛片久久久精品毛片| 精品久久久久久久久午夜福利| 国产成人AV综合久久| 人妻少妇久久中文字幕一区二区 | 波多野结衣AV无码久久一区| 亚洲∧v久久久无码精品| 久久精品这里只有精99品| 无码国内精品久久人妻| 久久精品国产99久久久香蕉| 国产亚洲综合久久系列| 久久亚洲sm情趣捆绑调教| 久久―日本道色综合久久| 久久精品aⅴ无码中文字字幕不卡| 99久久精品九九亚洲精品| 久久久久亚洲Av无码专| 免费精品久久天干天干| 久久综合丝袜日本网| 久久亚洲私人国产精品| 中文字幕无码av激情不卡久久| 久久99精品综合国产首页| 亚洲国产精品无码久久98| 亚洲国产香蕉人人爽成AV片久久 | 国产视频久久| 亚洲午夜精品久久久久久人妖| 麻豆一区二区99久久久久| 18禁黄久久久AAA片| 久久人人超碰精品CAOPOREN| 韩国三级中文字幕hd久久精品| 狠狠色婷婷综合天天久久丁香| 无码AV波多野结衣久久| 亚洲国产精品无码久久久蜜芽| 亚洲色大成网站www久久九 | 久久久WWW成人免费毛片| 欧美久久精品一级c片片|