const传奇

  • 来源: 互联网 作者: rocket   2008-03-18/13:40
  • 简介
    当我自己写程序需要用到const的时候,或者是读别人的代码碰到const的时候,我常常会停下来想一会儿。许多程序员从来不用const,理由是即使没用const他们也这么过来了。本文仅对const的用法稍作探讨,希望能够对提高软件的源代码质量有所帮助。

     

    常变量
    变量用const修饰,其值不得被改变。任何改变此变量的代码都会产生编译错误。Const加在数据类型前后均可。
    例如

    void main(void)
    
    {
    
        const int i = 10;    //i,j都用作常变量
    
        int const j = 20;
    
        i = 15;            //错误,常变量不能改变
    
        j = 25;            //错误,常变量不能改变
    
    }
    
    
    常指针
    Const跟指针一起使用的时候有两种方法。

    const可用来限制指针不可变。也就是说指针指向的内存地址不可变,但可以随意改变该地址指向的内存的内容。

    void main(void)
    
    {
    
        char* const str = "Hello, World";    //常指针,指向字符串
    
        *str = ''M'';            //可以改变字符串内容
    
        str = "Bye, World";        //错误,如能改变常指针指向的内存地址
    
    }
    
    
    const也可用来限制指针指向的内存不可变,但指针指向的内存地址可变。
    void main(void)
    
    {
    
        const char* str = "Hello, World";    //指针,指向字符串常量
    
        *str = ''M'';        //错误,不能改变字符串内容
    
        str = "Bye, World";    //修改指针使其指向另一个字符串
    
        *str = ''M'';        //错误,仍不能改变字符串内容
    
    }
    
    
    看完上面的两个例子,是不是糊涂了?告诉你一个诀窍,在第一个例子中,const用来修饰指针str,str不可变(也就是指向字符的常指针);第二个例子中,const用来修饰char*,字符串char*不可变(也就是指向字符串常量的指针)。

    这两种方式可以组合起来使用,使指针和内存内容都不可变。

    void main(void)
    
    {
    
        const char* const str = "Hello, World";        //指向字符串常量的常指针
    
        *str = ''M'';            //错误,不能改变字符串内容
    
        str = "Bye, World";        //错误,不能改变指针指向的地址
    
    }
    
    
    Const和引用
    引用实际上就是变量的别名,这里有几条规则:
    声明变量时必须初始化
    一经初始化,引用不能在指向其它变量。
    任何对引用的改变都将改变原变量。
    引用和变量本身指向同一内存地址。

    下面的例子演示了以上的规则:

    void main(void)
    
    {
    
        int i = 10;                    //i和j是int型变量
    
        int j = 20;        
    
        int &r = i;                    //r 是变量i的引用
    
        int &s;                        //错误,声明引用时必须初始化
    
        i = 15;                        //i 和 r 都等于15
    
        i++;                        //i 和 r都等于16
    
        r = 18;                        //i 和r 都等于18
    
        printf("Address of i=%u, Address of r=%u",&i,&r);    //内存地址相同
    
        r = j;                        //i 和 r都等于20,但r不是j的引用
    
        r++;                        //i 和 r 都等于21, j 仍等于20
    
    }
    
    
    用const修饰引用,使应用不可修改,但这并不耽误引用反映任何对变量的修改。Const加在数据类型前后均可。
    例如:
    void main(void)
    
    {
    
        int i = 10;
    
        int j = 100;
    
        const int &r = i;
    
        int const &s = j;
    
        r = 20;          //错,不能改变内容
    
        s = 50;          //错,不能改变内容
    
        i = 15;          // i和r 都等于15
    
        j = 25;          // j和s 都等于25
    
    }
    
    
    Const和成员函数
    声明成员函数时,末尾加const修饰,表示在成员函数内不得改变该对象的任何数据。这种模式常被用来表示对象数据只读的访问模式。例如:
    class MyClass
    
    {
    
        char *str ="Hello, World";
    
        MyClass()
    
        {
    
            //void constructor
    
        }
    
        
    
        ~MyClass()
    
        {
    
            //destructor
    
        }
    
    
    
        char ValueAt(int pos) const    //const method is an accessor method
    
        {
    
            if(pos >= 12)
    
                   return 0;
    
    		*str = ''M''; 	     //错误,不得修改该对象
    
            return str[pos];    	//return the value at position pos
    
        }
    
    }
    
    
    Const和重载
    重载函数的时候也可以使用const,考虑下面的代码:
    class MyClass
    
    {
    
        char *str ="Hello, World";
    
        MyClass()
    
        {
    
            //void constructor
    
        }
    
        
    
        ~MyClass()
    
        {
    
            //destructor
    
        }
    
    
    
        char ValueAt(int pos) const    //const method is an accessor method
    
        {
    
            if(pos >= 12)
    
                   return 0;
    
            return str[pos];    //return the value at position pos
    
        }
    
        
    
        char& ValueAt(int pos)        //通过返回引用设置内存内容
    
        {
    
            if(pos >= 12)
    
                   return NULL;
    
            return str[pos];
    
        }
    
    }
    
    

    在上面的例子中,ValueAt是被重载的。Const实际上是函数参数的一部分,在第一个成员函数中它限制这个函数不能改变对象的数据,而第二个则没有。这个例子只是用来说明const可以用来重载函数,没有什么实用意义。

    实际上我们需要一个新版本的GetValue。如果GetValue被用在operator=的右边,它就会充当一个变量;如果GetValue被用作一元操作符,那么返回的引用可以被修改。这种用法常用来重载操作符。String类的operator[]是个很好的例子。(这一段译得很烂,原文如下:In reality due to the beauty of references just the second definition of GetValue is actually required. If the GetValue method is used on the the right side of an = operator then it will act as an accessor, while if it is used as an l-value (left hand side value) then the returned reference will be modified and the method will be used as setter. This is frequently done when overloading operators. The [] operator in String classes is a good example.)

    class MyClass
    
    {
    
        char *str ="Hello, World";
    
        MyClass()
    
        {
    
            //void constructor
    
        }
    
        
    
        ~MyClass()
    
        {
    
            //destructor
    
        }
    
    
    
        char& operator[](int pos)        //通过返回引用可用来更改内存内容
    
        {
    
            if(pos >= 12)
    
                   return NULL;
    
            return str[pos];
    
        }
    
    }
    
    
    
    void main(void)
    
    {
    
        MyClass m;
    
        char ch = m[0];        //ch 等于 ''H''
    
        m[0] = ''M'';        //m的成员str变成:Mello, World
    
    }
    

    评论 {{userinfo.comments}}

    {{money}}

    {{question.question}}

    A {{question.A}}
    B {{question.B}}
    C {{question.C}}
    D {{question.D}}
    提交

    驱动号 更多