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

            旅途

            如果想飛得高,就該把地平線忘掉

            c++中const的完全解析

            http://blog.csdn.net/jsjwql/archive/2007/09/10/1779516.aspx

            1.?? const
            類型定義:指明變量或?qū)ο蟮闹凳遣荒鼙桓?/span> , 引入目的是為了取代預(yù)編譯指令

            2.?? 可以保護(hù)被修飾的東西,防止意外的修改,增強(qiáng)程序的健壯性。

            3.?? 編譯器通常不為普通 const 常量分配存儲(chǔ)空間,而是將它們保存在符號(hào)表中,這使得它成為一個(gè)編譯期間的常量,沒(méi)有了存儲(chǔ)與讀內(nèi)存的操作,使得它的效率也很高。

            4.??? 可以節(jié)省空間,避免不必要的內(nèi)存分配。

            ? 例如:

            ???? #define PI 3.14159???????? file:// 常量宏

            ???? const doulbe? Pi=3.14159;? file:// 此時(shí)并未將 Pi 放入 ROM

            ??????? ......

            ???? double i=Pi;???????????? file:// 此時(shí)為 Pi 分配內(nèi)存,以后不再分配!

            ???? double I=PI;?????????????? file:// 編譯期間進(jìn)行宏替換,分配內(nèi)存

            ???? double j=Pi;?????????????? file:// 沒(méi)有內(nèi)存分配

            ???? double J=PI;?????????????? file:// 再進(jìn)行宏替換,又一次分配內(nèi)存!

            ?const 定義常量從匯編的角度來(lái)看,只是給出了對(duì)應(yīng)的內(nèi)存地址,而不是象 #define 一樣給出的是立即數(shù),所以, const 定義的常量在程序運(yùn)行過(guò)程中只有一份拷貝,而 #define 定義的常量在內(nèi)存中有若干個(gè)拷貝。

            ?

            對(duì)于基本聲明

            1.? const int r=100; // 標(biāo)準(zhǔn) const 變量聲明加初始化,因?yàn)槟J(rèn)內(nèi)部連接所以必須被初始化,其作用域?yàn)榇宋募幾g器經(jīng)過(guò)類型檢查后直接用 100 在編譯時(shí)替換

            ?

            2.? extend const int r=100; // const 改為外部連接,作用于擴(kuò)大至全局,編譯時(shí)會(huì)分配內(nèi)存,并且可以不進(jìn)行初始化,僅僅作為聲明,編譯器認(rèn)為在程序其他地方進(jìn)行了定義

            但是如果外部想鏈接 r ,不能這樣用

            extern const int r=10;? // 錯(cuò)誤!常量不可以被再次賦值

            3. const int r[ ]={1,2,3,4};

            struct S {int a,b;};

            const S s[ ]={(1,2),(3.4)}; // 以上兩種都是常量集合,編譯器會(huì)為其分配內(nèi)存,所以不能在編譯期間使用其中的值,例如: int temp[r[2]]; 這樣的編譯器會(huì)報(bào)告不能找到常量表達(dá)式

            ? 但是

            ?const int Max=100;

            ?int Array[Max];?

            正確。

            ?還有

            ?

            ? 定義數(shù)組必須用常量,可以用 const 或者 #define 定義。 Static 雖然是編譯時(shí)確定,也不能用來(lái)聲明數(shù)組。

            ?

            對(duì)于指針和引用

            1.?? const int *r=&x; // 聲明 r 為一個(gè)指向常量的 x 的指針, r 指向的對(duì)象不能被修改,但他可以指向任何地址的常量

            pointer const 可以指定普通變量 , 用改指針不能修改它指向的對(duì)象,并不表示指向的對(duì)象是 const 不能被改變,例如:

            int i = 10;

            const int * p =? &i;

            *p = 11; //wrong

            ?

            ?i = 11 ; //correct

            自己的一個(gè)經(jīng)驗(yàn):一個(gè)具體的概念可以用范型的概念來(lái)賦值,但是一個(gè)范型的概念不能用具體的概念來(lái)賦值。

            我們可以把 const 指針當(dāng)成普通指針的父類,因?yàn)槠胀ㄖ羔樃膶懥?/span> const 屬性,而具有比 const 指針更多的功能。 這樣的話只有父類指針可以指向子類,而子類指針不能指向父類。

            2.?? int const *r=&x; // 與用法 1 完全等價(jià),沒(méi)有任何區(qū)別

            3.?? int * const r=&x; // 聲明 r 為一個(gè)常量指針,他指向 x r 這個(gè)指針的指向不能被修改,但他指向的地址的內(nèi)容可以修改

            4.? const int * const r=&x; // 綜合 1 3 用法, r 是一個(gè)指向常量的常量型指針

            5.?? const double & v;????? 該引用所引用的對(duì)象不能被更新

            ? 引用必須定義是初始話,而且初始化后這個(gè)引用不能指向其他的對(duì)象。但是這里加的 const 聲明不是這個(gè)意思,它是指不能改變 v 引用對(duì)象本身,也就是只能調(diào)用該對(duì)象里面的 const 成員函數(shù)。

            ?

            對(duì)于類型檢查

            可以把一個(gè)非 const 對(duì)象賦給一個(gè)指向 const 的指針,因?yàn)橛袝r(shí)候我們不想從這個(gè)指針來(lái)修改其對(duì)象的值;但是不可以把一個(gè) const 對(duì)象賦值給一個(gè)非 const 指針,因?yàn)檫@樣可能會(huì)通過(guò)這個(gè)指針改變指向?qū)ο蟮闹担泊嬖谑惯@種操作通過(guò)的合法化寫法,使用類型強(qiáng)制轉(zhuǎn)換可以通過(guò)指針改變 const 對(duì)象:

            const int r=100;

            int * ptr = const_cast<int*>(&r);? //C++ 標(biāo)準(zhǔn), C 語(yǔ)言使用: int * ptr =(int*)&r;

            ?

            對(duì)于字符數(shù)組

            ?

            char * name = “china”; 這樣的語(yǔ)句,在編譯時(shí)是能夠通過(guò)的,但是 ”china” 是常量字符數(shù)組,任何想修改他的操作也能通過(guò)編譯但會(huì)引起運(yùn)行時(shí)錯(cuò)誤,如果我們想修改字符數(shù)組的話就要使用 char name[ ] = “china”; 這種形式。

            ?

            對(duì)于函數(shù)

            1. void Fuction1 ( const int r ); // 此處為參數(shù)傳遞 const 值,意義是變量初值不能被函數(shù)改變

            2. const int Fuction1 (int); // 此處返回 const 值,意思指返回的原函數(shù)里的變量的初值不能被修改,但是函數(shù)按值返回的這個(gè)變量被制成副本,能不能被修改就沒(méi)有了意義,它可以被賦給任何的 const 或非 const 類型變量,完全不需要加上這個(gè) const 關(guān)鍵字。但這只對(duì)于內(nèi)部類型而言(因?yàn)閮?nèi)部類型返回的肯定是一個(gè)值,而不會(huì)返回一個(gè)變量,不會(huì)作為左值使用),對(duì)于用戶自定義類型,返回值是常量是非常重要的,見(jiàn)下面條款 3

            3.? Class CX; // 內(nèi)部有構(gòu)造函數(shù),聲明如 CX(int r =0)

            CX? Fuction1 () { return CX(); }

            const CX Fuction2 () { return CX(); }

            如有上面的自定義類 CX ,和函數(shù) Fuction1() Fuction2(), 我們進(jìn)行如下操作時(shí):

            Fuction1() = CX(1); // 沒(méi)有問(wèn)題,可以作為左值調(diào)用

            Fuction2() = CX(1); // 編譯錯(cuò)誤, const 返回值禁止作為左值調(diào)用。因?yàn)樽笾蛋逊祷刂底鳛樽兞繒?huì)修改其返回值, const 聲明禁止這種修改。

            4. ? 函數(shù)中指針的 const 傳遞和返回:

            int F1 (const char * pstr); // 作為傳遞的時(shí)候使用 const 修飾可以保證不會(huì)通過(guò)這個(gè)指針來(lái)修改傳遞參數(shù)的初值,這里在函數(shù)內(nèi)部任何修改 *pstr 的企圖都會(huì)引起編譯錯(cuò)誤。

            const char * F2 (); // 意義是函數(shù)返回的指針指向的對(duì)象是一個(gè) const 對(duì)象,它必須賦給一個(gè)同樣是指向 const 對(duì)象的指針。

            const char * const F3(); // 比上面多了一個(gè) const ,這個(gè) const 的意義只是在他被用作左值時(shí)有效,它表明了這個(gè)指針除了指向 const 對(duì)象外,它本身也不能被修改,所以就不能當(dāng)作左值來(lái)處理。

            5.?? 函數(shù)中引用的 const 傳遞:

            void F1 ( const X& px); // 這樣的一個(gè) const 引用傳遞和最普通的函數(shù)按值傳遞的效果是一模一樣的,他禁止對(duì)引用的對(duì)象的一切修改,唯一不同的是按值傳遞會(huì)先建立一個(gè)類對(duì)象的副本,然后傳遞過(guò)去,而它直接傳遞地址,所以這種傳遞比按值傳遞更有效。

            ** 另外只有引用的 const 傳遞可以傳遞一個(gè)臨時(shí)對(duì)象,因?yàn)榕R時(shí)對(duì)象都是 const 屬性,且是不可見(jiàn)的,他短時(shí)間存在一個(gè)局部域中,所以不能使用指針,只有引用的 const 傳遞能夠捕捉到這個(gè)家伙。

            6.? 有一點(diǎn)可以注意一下

            ??? const 為函數(shù)重載提供了一個(gè)參考。

            ???????? class A

            ???????? {

            ?????????? ......

            ?????????? void f(int i)?????? {......} file:// 一個(gè)函數(shù)

            ?????????? void f(int i) const {......} file:// 上一個(gè)函數(shù)的重載

            ??????????? ......

            ????????? };

            ?

            ??????? 關(guān)于函數(shù) overloading 不能根據(jù)返回值類型來(lái)確定

            ?

            ?? ?????double max( int a, int b);

            ??????? int??????? max( int a, int b);

            ??????? 也不能根據(jù)參數(shù)的默認(rèn)值來(lái)判斷

            ??????? int max( int a, int b);

            ??????? int max( int a, int b, int c=12);

            ??????? 一句話不能讓編譯器有多個(gè)選擇就 ok

            ?

            對(duì)于類

            1. ? 首先,對(duì)于 const 的成員變量,只能在構(gòu)造函數(shù)里使用初始化成員列表來(lái)初始化,試圖在構(gòu)造函數(shù)體內(nèi)進(jìn)行初始化 const 成員變量會(huì)引起編譯錯(cuò)誤。初始化成員列表形如:

            X:: X ( int ir ): r(ir) {} // 假設(shè) r 是類 X const 成員變量

            2.? const 成員函數(shù)。提到這個(gè)概念首先要談到 const 對(duì)象,正象內(nèi)置類型能夠定義 const 對(duì)象一樣( const int r=10; ),用戶自定義類型也可以定義 const 對(duì)象 (const X px(10);) ,編譯器要保證這個(gè)對(duì)象在其生命周期內(nèi)不能夠被改變。如果你定義了這樣的一個(gè) const 對(duì)象,那么對(duì)于這個(gè)對(duì)象的一切非 const 成員函數(shù)的調(diào)用,編譯器為了保證對(duì)象的 const 特性,都會(huì)禁止并在編譯期間報(bào)錯(cuò)。所以如果你想讓你的成員函數(shù)能夠在 const 對(duì)象上進(jìn)行操作的話,就要把這個(gè)函數(shù)聲明為 const 成員函數(shù)。假如 f( ) 是類中的成員函數(shù)的話,它的聲明形如:

            int f( ) const; //const 放在函數(shù)的最后,編譯器會(huì)對(duì)這個(gè)函數(shù)進(jìn)行檢查,在這個(gè)函數(shù)中的任何試圖改變成員變量和調(diào)用非 const 成員函數(shù)的操作都被視為非法

            ** 類的構(gòu)造和析構(gòu)函數(shù)都不能是 const 函數(shù)。

            3.? 建立了一個(gè) const 成員函數(shù),但仍然想用這個(gè)函數(shù)改變對(duì)象內(nèi)部的數(shù)據(jù)。這樣的一個(gè)要求也會(huì)經(jīng)常遇到,尤其是在一個(gè)苛刻的面試考官那里。首先我們要弄清楚考官的要求,因?yàn)橛袃煞N方法可以實(shí)現(xiàn),如果這位考官要求不改變?cè)瓉?lái)類的任何東西,只讓你從當(dāng)前這個(gè) const 成員函數(shù)入手,那么你只有使用前面提到的類型強(qiáng)制轉(zhuǎn)換方法。實(shí)例如下:

            // 假如有一個(gè)叫做 X 的類,它有一個(gè) int 成員變量 r ,我們需要通過(guò)一個(gè) const 成員函數(shù) f( ) 來(lái)對(duì)這個(gè) r 進(jìn)行 ++r 操作,代碼如下

            void X::f( ) const

            {? (const_cast<X*>(this)) -> ++r;? } // 通過(guò) this 指針進(jìn)行類型強(qiáng)制轉(zhuǎn)換實(shí)現(xiàn)

            另外一種方法就是使用關(guān)鍵字: mutable 。如果你的成員變量在定義時(shí)是這個(gè)樣子的:

            mutable int r ;

            那么它就告訴編譯器這個(gè)成員變量可以通過(guò) const 成員函數(shù)改變。編譯器就不會(huì)再理會(huì)對(duì)他的檢查了。

            ?

            關(guān)于 const 一些問(wèn)題

            ?[ 思考 1] 以下的這種賦值方法正確嗎?

            ?const A_class* c=new A_class();

            ?A_class* e = c;

            這種方法不正確,因?yàn)槁暶髦羔樀哪康氖菫榱藢?duì)其指向的內(nèi)容進(jìn)行改變,而聲明的指針 e 指向的是一個(gè)常量,所以不正確;

            [ 思考 2] 以下的這種賦值方法正確嗎?

            ?A_class* const c = new A_class();

            ?A_class* b = c;

            這種方法正確,因?yàn)槁暶髦羔標(biāo)赶虻膬?nèi)容可變;

            [ 思考 3] 這樣定義賦值操作符重載函數(shù)可以嗎?

            const A_class& operator=(const A_class& a);

            不正確;在 const A_class::operator=(const A_class& a) 中,參數(shù)列表中的 const 的用法正確,而當(dāng)這樣連續(xù)賦值的時(shí)侯,問(wèn)題就出現(xiàn)了: A_class a,b,c:(a=b)=c; 因?yàn)?/span> a.operator=(b) 的返回值是對(duì) a const 引用,不能再將 c 賦值給 const 常量。

            ?

            ?

            幾點(diǎn)值得討論的地方:
            1 const 究竟意味著什么?
            ?
            說(shuō)了這么多,你認(rèn)為 const 意味著什么?一種修飾符?接口抽象?一種新類型?
            ?
            也許都是,在 Stroustup 最初引入這個(gè)關(guān)鍵字時(shí),只是為對(duì)象放入 ROM 做出了一種可能,對(duì)于 const 對(duì)象, C++ 既允許對(duì)其進(jìn)行靜態(tài)初始化,也允許對(duì)他進(jìn)行動(dòng)態(tài)初始化。理想的 const 對(duì)象應(yīng)該在其構(gòu)造函數(shù)完成之前都是可寫的,在析夠函數(shù)執(zhí)行開(kāi)始后也都是可寫的,換句話說(shuō), const 對(duì)象具有從構(gòu)造函數(shù)完成到析夠函數(shù)執(zhí)行之前的不變性,如果違反了這條規(guī)則,結(jié)果都是未定義的!雖然我們把 const 放入 ROM 中,但這并不能夠保證 const 的任何形式的墮落,我們后面會(huì)給出具體的辦法。無(wú)論 const 對(duì)象被放入 ROM 中,還是通過(guò)存儲(chǔ)保護(hù)機(jī)制加以保護(hù),都只能保證,對(duì)于用戶而言這個(gè)對(duì)象沒(méi)有改變。換句話說(shuō),廢料收集器(我們以后會(huì)詳細(xì)討論,這就一筆帶過(guò))或數(shù)據(jù)庫(kù)系統(tǒng)對(duì)一個(gè) const 的修改怎沒(méi)有任何問(wèn)題。
            2 )位元 const V.S. 抽象 const?
            對(duì)于關(guān)鍵字 const 的解釋有好幾種方式,最常見(jiàn)的就是位元 const 抽象 const 。下面我們看一個(gè)例子:
            ??????? class A
            ??????? {
            ???????? public:
            ?????????????? ......
            ?????????????? A f(const A& a);
            ?????????????? ......
            ???????? };
            如果采用抽象 const 進(jìn)行解釋,那就是 f 函數(shù)不會(huì)去改變所引用對(duì)象的抽象值,如果采用位元 const 進(jìn)行解釋,那就成了 f 函數(shù)不會(huì)去改變所引用對(duì)象的任何位元。
            我們可以看到位元解釋正是 c++ 對(duì) const 問(wèn)題的定義, const 成員函數(shù)不被允許修改它所在對(duì)象的任何一個(gè)數(shù)據(jù)成員。
            為什么這樣呢?因?yàn)槭褂梦辉?/span> const 2 個(gè)好處:
            ?
            最大的好處是可以很容易地檢測(cè)到違反位元 const 規(guī)定的事件:編譯器只用去尋找有沒(méi)有對(duì)數(shù)據(jù)成員的賦值就可以了。另外,如果我們采用了位元 const ,那么,對(duì)于一些比較簡(jiǎn)單的 const 對(duì)象,我們就可以把它安全的放入 ROM 中,對(duì)于一些程序而言,這無(wú)疑是一個(gè)很重要的優(yōu)化方式。(關(guān)于優(yōu)化處理,我們到時(shí)候?qū)iT進(jìn)行討論)
            當(dāng)然,位元 const 也有缺點(diǎn),要不然,抽象 const 也就沒(méi)有產(chǎn)生的必要了。
            首先,位元 const 的抽象性比抽象 const 的級(jí)別更低!實(shí)際上,大家都知道,一個(gè)庫(kù)接口的抽象性級(jí)別越低,使用這個(gè)庫(kù)就越困難。
            其次,使用位元 const 的庫(kù)接口會(huì)暴露庫(kù)的一些實(shí)現(xiàn)細(xì)節(jié),而這往往會(huì)帶來(lái)一些負(fù)面效應(yīng)。所以,在庫(kù)接口和程序?qū)崿F(xiàn)細(xì)節(jié)上,我們都應(yīng)該采用抽象 const
            有時(shí),我們可能希望對(duì) const 做出一些其它的解釋,那么,就要注意了,目前,大多數(shù)對(duì) const 的解釋都是類型不安全的,這里我們就不舉例子了,你可以自己考慮一下,總之,我們盡量避免對(duì) const 的重新解釋。
            3 )放在類內(nèi)部的常量有什么限制?
            ?
            看看下面這個(gè)例子:
            ????class A
            ????{
            ??????private:
            ?????????? const int c3 = 7;?????????? // ???
            ?? ??? ???static int c4 = 7;????????? // ???
            ?? ??? ?????static const float c5 = 7;? // ???
            ????????? ......
            ? ???};
            你認(rèn)為上面的 3 句對(duì)嗎?呵呵,都不對(duì)!使用這種類內(nèi)部的初始化語(yǔ)法的時(shí)候,常量必須是被一個(gè)常量表達(dá)式初始化的整型或枚舉類型,而且必須是 static const 形式。這顯然是一個(gè)很嚴(yán)重的限制!
            ?
            那么,我們的標(biāo)準(zhǔn)委員會(huì)為什么做這樣的規(guī)定呢?一般來(lái)說(shuō),類在一個(gè)頭文件中被聲明,而頭文件被包含到許多互相調(diào)用的單元去。但是,為了避免復(fù)雜的編譯器規(guī)則, C++ 要求每一個(gè)對(duì)象只有一個(gè)單獨(dú)的定義。如果 C++ 允許在類內(nèi)部定義一個(gè)和對(duì)象一樣占據(jù)內(nèi)存的實(shí)體的話,這種規(guī)則就被破壞了。
            4 )如何初始化類內(nèi)部的常量?
            ?
            一種方法就是 static const 并用,在內(nèi)部初始化,如上面的例子;
            另一個(gè)很常見(jiàn)的方法就是初始化列表:
            ??????class A
            ????? {
            ????????? public:
            ??????????????? A(int i=0):test(i) {}
            ????????? private:
            ??????????????? const int i;
            ???????}

            ??????
            還有一種方式就是在外部初始化,例如:
            ??????class A
            ??????{
            ????????? public:
            ??????????????? A() {}
            ????????? private:
            ??????????????? static const int i;? file://注
            意必須是靜態(tài)的!
            ???????}

            ????????? const int A::i=3;
            5 )常量與數(shù)組的組合有什么特殊嗎?
            ??
            我們給出下面的代碼:
            ?????????? const int size[3]={10,20,50};
            ?????????? int array[size[2]];
            有什么問(wèn)題嗎?對(duì)了,編譯通不過(guò)!為什么呢?
            ?const
            可以用于集合,但編譯器不能把一個(gè)集合存放在它的符號(hào)表里,所以必須分配內(nèi)存。在這種情況下, const 意味著 不能改變的一塊存儲(chǔ) 。然而,其值在編譯時(shí)不能被使用,因?yàn)榫幾g器在編譯時(shí)不需要知道存儲(chǔ)的內(nèi)容。自然,作為數(shù)組的大小就不行了:)
            ?
            你再看看下面的例子:
            ???????class A
            ???????{
            ????????? public:
            ??????????????? A(int i=0):test[2]({1,2}) {} file://你
            認(rèn)為行嗎?
            ????????? private:
            ??????????????? const int test[2];
            ????????}

            vc6
            下編譯通不過(guò),為什么呢?
            關(guān)于這個(gè)問(wèn)題,前些時(shí)間, njboy 問(wèn)我是怎么回事?我反問(wèn)他: 你認(rèn)為呢? 他想了想,給出了一下解釋,大家可以看看:我們知道編譯器堆初始化列表的操作是在構(gòu)造函數(shù)之內(nèi),顯式調(diào)用可用代碼之前,初始化的次序依據(jù)數(shù)據(jù)聲明的次序。初始化時(shí)機(jī)應(yīng)該沒(méi)有什么問(wèn)題,那么就只有是編譯器對(duì)數(shù)組做了什么手腳!其實(shí)做什么手腳,我也不知道,我只好對(duì)他進(jìn)行猜測(cè):編譯器搜索到 test 發(fā)現(xiàn)是一個(gè)非靜態(tài)的數(shù)組,于是,為他分配內(nèi)存空間,這里需要注意了,它應(yīng)該是一下分配完,并非先分配 test[0], 然后利用初始化列表初始化,再分配 test[1], 這就導(dǎo)致數(shù)組的初始化實(shí)際上是賦值!然而,常量不允許賦值,所以無(wú)法通過(guò)。
            呵呵,看了這一段冠冕堂皇的話,真讓我笑死了! njboy 別怪我揭你短呀:)我對(duì)此的解釋是這樣的: C++ 標(biāo)準(zhǔn)有一個(gè)規(guī)定,不允許無(wú)序?qū)ο笤陬悆?nèi)部初始化,數(shù)組顯然是一個(gè)無(wú)序的,所以這樣的初始化是錯(cuò)誤的!對(duì)于他,只能在類的外部進(jìn)行初始化,如果想讓它通過(guò),只需要聲明為靜態(tài)的,然后初始化。
            ?
            這里我們看到,常量與數(shù)組的組合沒(méi)有什么特殊!一切都是數(shù)組惹的禍!
            6 this 指針是不是 const 類型的?
            ?this
            指針是一個(gè)很重要的概念,那該如何理解她呢?也許這個(gè)話題太大了,那我們縮小一些: this 指針是個(gè)什么類型的?這要看具體情況:如果在非 const 成員函數(shù)中, this 指針只是一個(gè)類類型的;如果在 const 成員函數(shù)中, this 指針是一個(gè) const 類類型的;如果在 volatile 成員函數(shù)中 ,this 指針就是一個(gè) volatile 類類型的。
            7 const 到底是不是一個(gè)重載的參考對(duì)象?
            ???????
            先看一下下面的例子:
            ??????? class A
            ???????? {
            ??????????????? ? ......
            ?????????? ???? void f(int i)?????? {......} file://一
            個(gè)函數(shù)
            ?????????? ???? void f(int i) const {......} file://上
            一個(gè)函數(shù)的重載
            ??????????? ??? ......
            ????????? };
            ???????
            上面是重載是沒(méi)有問(wèn)題的了,那么下面的呢?
            ???????? class A
            ???????? {
            ??????????????? ......
            ?????????? ???? void f(int i)?????? {......} file://一
            個(gè)函數(shù)
            ??????????????? void f(const int i) {......} file://?????
            ??????????????? ? ......
            ???????? };
            這個(gè)是錯(cuò)誤的,編譯通不過(guò)。那么是不是說(shuō)明內(nèi)部參數(shù)的 const 不予重載呢?再看下面的例子:
            ??????? class A
            ???????? {
            ??????????????? ......
            ?????????? ???? void f(int& )?????? {......} file://一
            個(gè)函數(shù)
            ??????????????? void f(const int& ) {......} file://?????
            ??????????????? ......
            ???????? };
            ?
            這個(gè)程序是正確的,看來(lái)上面的結(jié)論是錯(cuò)誤的。為什么會(huì)這樣呢?這要涉及到接口的透明度問(wèn)題。按值傳遞時(shí),對(duì)用戶而言,這是透明的,用戶不知道函數(shù)對(duì)形參做了什么手腳,在這種情況下進(jìn)行重載是沒(méi)有意義的,所以規(guī)定不能重載!當(dāng)指針或引用被引入時(shí),用戶就會(huì)對(duì)函數(shù)的操作有了一定的了解,不再是透明的了,這時(shí)重載是有意義的,所以規(guī)定可以重載。
            8 )什么情況下為 const 分配內(nèi)存?
            ???????
            以下是我想到的可能情況,當(dāng)然,有的編譯器進(jìn)行了優(yōu)化,可能不分配內(nèi)存。
            ??????? A
            、作為非靜態(tài)的類成員時(shí);
            ??????? B
            、用于集合時(shí);
            ??????? C
            、被取地址時(shí);
            ??????? D
            、在 main 函數(shù)體內(nèi)部通過(guò)函數(shù)來(lái)獲得值時(shí);
            ??????? E
            const class struct 有用戶定義的構(gòu)造函數(shù)、析構(gòu)函數(shù)或基類時(shí);。
            ??????? F
            、當(dāng) const 的長(zhǎng)度比計(jì)算機(jī)字長(zhǎng)還長(zhǎng)時(shí);
            ??????? G
            、參數(shù)中的 const
            ??????? H
            、使用了 extern 時(shí)。
            ???????
            不知道還有沒(méi)有其他情況,歡迎高手指點(diǎn):) ???????
            9 )臨時(shí)變量到底是不是常量?
            很多情況下,編譯器必須建立臨時(shí)對(duì)象。像其他任何對(duì)象一樣,它們需要存儲(chǔ)空間而且必須被構(gòu)造和刪除。區(qū)別是我們從來(lái)看不到編譯器負(fù)責(zé)決定它們的去留以及它們存在的細(xì)節(jié)。對(duì)于 C++ 標(biāo)準(zhǔn)草案而言:臨時(shí)對(duì)象自動(dòng)地成為常量。因?yàn)槲覀兺ǔ=佑|不到臨時(shí)對(duì)象,不能使用與之相關(guān)的信息,所以告訴臨時(shí)對(duì)象做一些改變有可能會(huì)出錯(cuò)。當(dāng)然,這與編譯器有關(guān),例如: vc6 vc7 都對(duì)此作了擴(kuò)展,所以,用臨時(shí)對(duì)象做左值,編譯器并沒(méi)有報(bào)錯(cuò)。
            10 )與 static 搭配會(huì)不會(huì)有問(wèn)題?
            ???????
            假設(shè)有一個(gè)類:
            ??????? class A
            ??????? {
            ???????? public:
            ??????????????? ......
            ???????????? ?? static void f() const { ......}
            ??????????????? ......
            ???????? };
            ??
            我們發(fā)現(xiàn)編譯器會(huì)報(bào)錯(cuò),因?yàn)樵谶@種情況下 static 不能夠與 const 共存!
            ??
            為什么呢?因?yàn)?/span> static 沒(méi)有 this 指針,但是 const 修飾 this 指針,所以 ...
            ?
            11 )如何修改常量?
            ??
            有時(shí)候我們卻不得不對(duì)類內(nèi)的數(shù)據(jù)進(jìn)行修改,但是我們的接口卻被聲明了 const ,那該怎么處理呢?我對(duì)這個(gè)問(wèn)題的看法如下:
            ??1
            )標(biāo)準(zhǔn)用法: mutable
            ????????????? class A
            ????????????? {
            ?????????????? public:
            ????????????????????? A(int i=0):test(i)??????? { }
            ????????????????????? void SetValue(int i)const { test=i; }
            ?????????????? private:
            ????????????????????? mutable int test;?? file://這
            里處理!
            ?????????????? }
            2 )強(qiáng)制轉(zhuǎn)換: const_cast
            ?????????????? class A
            ?????????????? {
            ?????????????? public:
            ????????????????????? A(int i=0):test(i)??????? { }
            ????????????????????? void SetValue(int i)const
            ????????????????????? { const_cast <int>(test)=i; }//
            這里處理!
            ?????????????? private:
            ????????????????????? int test;??
            ?????????????? }
            3 )靈活的指針: int*
            ?????????????? class A
            ????????????? {
            ?????????????? public:
            ????????????????????? A(int i=0):test(i)??????? { }
            ????????????????????? void SetValue(int i)const
            ????????????????????? { *test=i; }
            ?????????????? private:
            ????????????????????? int* test;?? file://這
            里處理!
            ?????????????? }

            4
            )未定義的處理
            ????????????? class A
            ????????????? {
            ?????????????? public:
            ????????????????????? A(int i=0):test(i)??????? { }
            ????????????????????? void SetValue(int i)const
            ????????????????????? { int *p=(int*)&test; *p=i; }//
            這里處理!
            ?????????????? private:
            ????????????????????? int test;??
            ?????????????? }

            ???????????????
            注意,這里雖然說(shuō)可以這樣修改,但結(jié)果是未定義的,避免使用!
            5
            )內(nèi)部處理: this 指針
            ????????????? class A
            ????????????? {
            ?????????????? public:
            ????????????????????? A(int i=0):test(i)??????? { }
            ????????????????????? void SetValue(int i)const
            ????????????????????? { ((A*)this)->test=i; }//
            這里處理!
            ?????????????? private:
            ????????????????????? int test;??
            ?????????????? }

            ???????????? 6
            )最另類的處理:空間布局
            ?????????????? class A
            ?????????????? {
            ??????????????? public:
            ????????????????????? A(int i=0):test(i),c('a') {? }
            ??????????????? private:
            ????????????????????? char c;
            ????????????????????? const int test;
            ??????????????? };
            ??????????????? int main()
            ??????????????? {
            ??????????????????? A a(3);
            ??????????????????? A* pa=&a;
            ??????????????????? char* p=(char*)pa;????
            ??????????????????? int*? pi=(int*)(p+4
            ); // 利用邊緣調(diào)整
            ??????????????????? *pi=5;???????????????? file://此
            處改變了 test 的值!
            ??????????????????? return 0;
            ???????????????? }
            雖然我給出了 6 中方法,但是我只是想說(shuō)明如何更改,但出了第一種用法之外,另外 5 種用法,我們并不提倡,不要因?yàn)槲疫@么寫了,你就這么用,否則,我真是要誤人子弟了:) ??
            12 )最后我們來(lái)討論一下常量對(duì)象的動(dòng)態(tài)創(chuàng)建。
            ??
            既然編譯器可以動(dòng)態(tài)初始化常量,就自然可以動(dòng)態(tài)創(chuàng)建,例如:
            ??const int* pi=new const int(10);
            這里要注意 2 點(diǎn):
            ?1
            const 對(duì)象必須被初始化!所以 (10) 是不能夠少的。
            ?2
            new 返回的指針必須是 const 類型的。
            ?
            那么我們可不可以動(dòng)態(tài)創(chuàng)建一個(gè)數(shù)組呢?答案是否定的,因?yàn)?/span> new 內(nèi)置類型的數(shù)組,不能被初始化。
            ?
            這里我們忽視了數(shù)組是類類型的,同樣對(duì)于類內(nèi)部數(shù)組初始化我們也做出了這樣的忽視,因?yàn)檫@涉及到數(shù)組的問(wèn)題,我們以后再討論。
            ?


            ??????????

            Reference:

            http://blog.csdn.net/boox/archive/2005/05/30/384509.aspx

            http://www.bloghome.cn/posts/61287.html

            http://blog.csdn.net/hwalk/archive/2006/05/20/746471.aspx

            http://blog.csdn.net/hustli/archive/2003/06/30/19342.aspx

            ?

            posted on 2007-10-06 01:43 旅途 閱讀(154) 評(píng)論(0)  編輯 收藏 引用 所屬分類: C/C++

            99久久精品久久久久久清纯| 久久亚洲精品无码VA大香大香| 国产巨作麻豆欧美亚洲综合久久| 亚洲国产成人久久综合区| 亚洲AV无码成人网站久久精品大| 日本精品久久久中文字幕| 久久久国产99久久国产一| 色成年激情久久综合| 少妇久久久久久被弄高潮| 久久综合五月丁香久久激情| 国产精品久久一区二区三区| 久久亚洲日韩看片无码| 久久综合久久性久99毛片| 99久久国产免费福利| 99国产欧美久久久精品蜜芽| 囯产极品美女高潮无套久久久| 精品无码久久久久久国产| 久久精品免费一区二区三区| 色欲av伊人久久大香线蕉影院 | 久久这里只有精品久久| 亚洲午夜久久久影院| 一本色综合久久| 麻豆国内精品久久久久久| 91麻精品国产91久久久久| 浪潮AV色综合久久天堂| 77777亚洲午夜久久多喷| 亚洲午夜无码AV毛片久久| 久久久久久国产精品无码下载 | 国产精品久久久久影视不卡| 日本人妻丰满熟妇久久久久久| 欧美国产成人久久精品| 免费无码国产欧美久久18| 国产精品成人久久久| 婷婷久久综合九色综合九七| 久久精品国产亚洲7777| 国产一区二区精品久久岳| 香蕉久久一区二区不卡无毒影院| 91精品国产91久久综合| 国产精品福利一区二区久久| 久久精品国产只有精品2020| 一本大道加勒比久久综合|