C++ const學習

 

概念安全

  const就是爲了直接表達「不變化的值」這一律念。也就是說該值只可讀,不可直接寫。
  因爲不能夠修改,因此const常量在聲明的時候必須初始化函數

    const int a;    //error
    extern    const int ext_a;

 

做用this

  •  能夠定義const常量,具備不可變性 
        const int a = 4 ;
        //a = 5;      //error
  • 便於類型檢查,使編譯器對處理內容有更多瞭解
    如 a = 5 在編譯的時候能夠將對const常量進行修改的部分檢查出來
  • 保護被修飾的內容
    咱們一直在建議不要修改函數的參數值,便於調試、維護,以及減小沒必要要的錯誤,但函數的調用者與函數的編寫者,因此沒法人爲的保證傳入的參數沒法被修改,此時就運用const,運用編譯器對代碼進行檢查。主要仍是和引用參數聯合使用,若是隻是修改參數對調用者沒影響還好說,不然...(後續詳談)
    void fun1(const int a)
    {
        //a=5;
    }
    
    void fun2(const ClassA& a)
    {
        //a.xx=xx 
    }
  • 提升代碼的可讀性、維護性
    運用const常量替換代碼中出現的比較多的各類文字量,我的認爲代碼中出現數字0、1,閱讀時還能理解,可是要是忽然出來一個二、五、8,這是什麼意思呢?可能本身寫的代碼過一陣子本身也不清楚了,此時咱們就能夠運用const常量或enum起一個合適的名字替代這些不易理解的數字。若是是字符串的話就只能運用const了,呃,或者是宏#define(我的不太喜歡宏,緣由1.宏易出錯,不易理解;2.編譯器沒法檢查類型;3.C++不建議使用宏)
  • 函數重載
    兩個重載函數必須在下列一個或兩個方面有所區別:
    一、參數數量不一樣
    二、參數類型不一樣
      以下 funA以上兩個方面都不知足,可是卻能夠重載,const函數對應const對象使用(後續詳談)
  • class ClassA
    {
    public:
        void funA()
        {
       //... }
    void funA() const { //... } }; 

 const與指針spa

  The C++ Programming Language裏面給出過一個助記的方法:  把一個聲明從右向左讀。翻譯

    char * const p1;          //p1 is a const pointer to char
    const char *p2;            //p2 is a pointer to const char
    const char * const p3;    //p3 is a const pointer to const char

  Effective C++一樣給出了一種方式,若是關鍵字const在星號的左邊,表示被指物是常量;若是出如今星號右邊,表示指針自身是常量;若是出如今兩邊,表示被指物和指針兩者都是常量。其實指針只要分清指針自己與所指向的內容便可。我的以爲不用糾結與有些書上的叫法什麼「指針常量」,「常量指針」,這都是在翻譯的過程當中帶來的歧義。指針

  如p1是一個const pointer,因此在聲明的時候必須初始化,不然編譯不經過,而*p1則是char類型。
  p2是一個pointer但不是const,*P2纔是const類型,因此p2能夠不用初始化。調試

  那麼p1聲明指向的爲char 是否能夠指向const char 呢?p2聲明指向的爲const char 是否能夠指向char類型呢?
code

    const char ca = 'a' ;
    char b= 'b';

    char *p;
    //p=&ca;                //error
    p=&b;
    char * const p1=&b;
    //char * const p1=&ca;        //error    
    const char *p2;
    p2=&ca;
    p2=&b;                        //ok
    const char * const p3=&b;    //ok

 

  由於對承諾不修改的內容要被修改,確定是有問題的;但對可修改的內容不作修改沒有任何問題。如上面ca不可修改,*p能夠修改,因此p=&ca錯誤;而b能夠修改,*p1不能夠修改,p=&b對b不會形成不良影響,因此能夠經過。對象

  那麼是否是非const類型能夠直接賦值與const類型呢?而const類型不能直接賦值與非const類型呢?blog

    ClassA ca;
    const ClassA cst_b;

    ClassA cc=cst_b;    //copy構造函數能夠理解
    ClassA c2;
    c2=cst_b;            //??
    const ClassA cst_d=ca;     

    int a=1;
    const int b=a;
    int c=b;            //??

  以上代碼徹底能夠編譯經過,那該怎麼解釋呢?我的理解爲若是賦值後的對象不對原對象代碼不良影響,都是能夠經過的。如int c=b;c的修改不會修改b;c2=cst_b,調用ClassA的賦值操做ClassA& operator=(const ClassA&),也一樣不會對原cst_b修改。

 const與引用

   引用與指針有所不一樣,由於引用自己能夠看做是一個常量指針,引用在聲明是必須初始化,且不能夠在引用值其餘對象。因此引用只存在一種形式。const type& 而type& 與type& const 等價。const 引用主要運用在函數的參數傳遞方面。Effective C++ 第20條 Perfer pass-by-reference-to-const to pass-by-value.

    int a;
    int & ref1=a;
    const int & ref2 =a;
    int & const ref3=a;        //不必

const與函數

   函數與const 的關係能夠從三部分來看,返回值、參數、函數自身

  • const修飾返回值
    class ClassA
    {
    public:
        int a;
    
        ClassA():a(1)
        {
        }
        const int funA()   //沒意義,由於返回值自己就沒法修改 與int funA()同樣,並且也不存在funA()=4這種寫法
        {
            return a;    
        }
        int * const funB() //與funA同樣,const的限定的是返回值的指針,也沒法修改 。與int *  funB() 同樣
        {
            return &a;
        }
        const int * funC() //const修飾的是返回指針所指內容,因此該函數的接收這也必須爲const int*類型
        {                        
            return &a;
        }
        const int &funD()   //返回引用,該引用不能夠修改
        {
            return a;
        }
        void test()
        {
            int re=funA();
            int *p=    funB();
    
            //int *p1=funC();        //error
            const int *p2=funC();
    
            //int& c=funD();         //error
            const int& a2=funD();
             
        }
    };

     funA、funB其實實際意義都不大,由於不論返回值是否是const類型,函數調用者都不可能修改返回值的實際值。而函數調用者該不應用const與函數自己不要緊。
    cosnt自定義類型返回值,每每能夠下降因函數調用者錯誤而形成的之外,而又不至於放棄安全性和高效性

    ClassA funCA()
    {
        ClassA a;
        return a;
    }
    
    int _tmain(int argc, _TCHAR* argv[])
    {
        ClassA ca;
        funCA()=ca;
    }
      funCA()=ca;這句話具體有什麼實際意義呢?沒意義,可是就是能夠編譯經過,此時就能夠將funCA返回值限定爲const ClassA,這樣的寫法首先編譯器都不經過。
  • const修飾函數參數
      Effective C++ 至於const參數,沒什麼特別新穎的觀念,它們不過就像local const對象同樣,你應該在必要使用它們的時候使用它們。除非你有須要修改參數或者loacl對象,不然請將他們聲明爲const。
        int funA(const int a);
        int funB(int * const p);
        int funC(const int *p);
        int funD(const int& ra);
  • const修飾成員函數自身
    將const實施於成員函數的目的,是爲了確認該成員函數能夠做用與const對象身上。這類函數有兩個理由顯得重要
    1.是class接口比較容易被理解。2.const對象使用
    class ClassA
    {
    
    public:
        int a;
    
        ClassA():a(1)
        {
        }
    
        void fun()
        {
            a=5;
            cout<<"this is not a const function"<<endl;
        }
        void fun() const
        {
            //    a=5;    //error
            cout<<"this is a const function"<<endl;
        }
    };
    int _tmain(int argc, _TCHAR* argv[])
    {
    
        ClassA ca;
        ca.fun();    //this is not a const function
    
        const ClassA cb;
        cb.fun();    //this is a const function
    }

    const對象只能調用const函數,且const函數不能對成員函數作修改。若將void fun()函數刪掉,則編譯不經過錯誤提示:ClassA::fun」: 不能將「this」指針從「const ClassA」轉換爲「ClassA &;若將void fun() const 函數刪掉,則ca.fun()調用const fun。

   今天快下班了,先寫這些吧,明天補充總結!

相關文章
相關標籤/搜索