C/C++中const修饰符总结

来源:互联网 发布:彩票自动分析软件 编辑:程序博客网 时间:2024/06/06 12:28

C/C++中的const是一个修饰符,它允许你指定一个语义上的约束,也就是可以通过const指定一个“不该被改动”的对象,而编译器会强制实施这项约束。

const语法很多 但都不复杂 下面我将分别讲述各种语法及其作用。

在讲述const修饰符用在指针上有什么效果之前先来看下指针不加const修饰符的情况:

    int Num1 = 10;    int Num2 = 20;    int* p = &Num1;    //将指向int型指针变量p指向Num1    *p = 55;           //Good!     p = &Num2;         //Good!
以上代码在编译时是没有任何问题的 指针变量p可随意改变所指向的地址 也可以随意改变指针p所指向的数据 此时该指针p是没有约束的。

但是当指针p加上const修饰符进行约束后 又会是怎样的效果呢?看如下代码:

    int Num1 = 10;    int Num2 = 20;        //形式1    const int* p = &Num1;    p* = 55;                //error!    p = &Num2;              //Good!        //形式2    int* const p1 = &Num1;    *p1 = 66;               //Good!    p1 = &Num2;             //error!        //形式3    const int* const p2 = &Num1;    *p2 = 77;               //error!    p2 = &Num2;             //error!
如上所示 对指针进行const修饰有3种形式 

第1种形式 const在 * 前面 表示的是常量指针 也就是说该指针变量p所存储的地址可以改变 但是地址所处的数据无法更改,而p* = 55;这行代码因为试图更改地址所处的数据而被编译器所禁止 所以编译不通过。而该种形式又有俩种写法:const int* p;和int const *p; 这俩种写法是等价的。

第2种形式 const在 * 后面 表示的是指针常量 也就是说该指针变量p1所存储的地址不能改变 但是地址所处的数据可以更改,而p1 = &Num2;这行代码试图改变p1所存储的地址所以编译器也是不允许的 从而编译不通过。

第3种形式 是前俩种形式的结合 表示该指针变量p2即不可以改变所存储的地址 也不能更改地址所处的数据,所以*p2 = 77;试图改变地址所处的数据和p2 = &Num2;试图改变指针变量所存储的地址 均是编译器不允许的。

另外 const修饰符也可运用在内置类型和用户自定义类型上 如下代码:

int main(void){    const int SIZE = 10;      //不可修改    const float f1 = 13.5;    //不可修改    const char c = 'A';       //不可修改    int Num[SIZE];            //定义一个int数组 有SIZE(10)个元素    return 0;}
用内置类型定义变量并且用const进行修饰 则该变量的值不可修改(常变量)而且必须在定义的时候进行初始化。

假设有如下类定义:

class Base{private:    static const int SIZE = 5;    int NumArr[SIZE];    const int ID;public:    Base(int id_t);    void show()const;    void setValue(int index_t,int value_t);};Base::Base(int id_t):ID(id_t){   //ID为常变量 需要在成员初始化列表中进行初始化 注:成员初始化列表只能在构造函数中使用    for(int i=0;i<SIZE;++i){        NumArr[i] = 0;    }}void Base::show()const{    std::cout << "ID:" << ID << std::endl;    for(int i=0;i<SIZE;++i){        std::cout << NumArr[i] << " ";    }    std::cout << std::endl;}void Base::setValue(int index_t,int value_t){    NumArr[index_t] = value_t;}
如上代码void Base::show()const;  将const修饰符用在成员函数身上,将约束该成员函数,规定其不允许对当前调用对象进行修改,也就是只能读取该对象的数据但不能修改,并且当对成员函数进行const修饰后,该成员函数将不允许调用非const修饰的成员函数,也就是说 在当前代码中 show()的实现体不能对成员函数setValue()进行调用,因为它没有经过const修饰,所以可能会对调用对象进行修改,而show()的意义就是不允许修改对象,这将引起矛盾,所以编译器是绝对禁止该调用行为的。但是setValue()函数可以内部调用show()函数。const成员函数还有一个作用就是使const对象成为可能,这将在下面讲述。

假设有如下代码:

    Base s1(1001);    s1.show();             //Good!    s1.setValue(1,6);      //Good!    s1.show();             //Good!    const Base s2(1002);    s2.show();             //Good!    s2.setValue(1,8);      //error!
s1为非const对象 所以调用该对象的任何成员函数都是合法的 并且setValue()是非const成员函数所以也可以对该对象进行修改

s2是加了const修饰符的对象 所以该对象是不允许修改的 而且只能调用const成员函数 非const成员函数不允许调用,因为上面说了,对象本身是不允许修改的,而const成员函数本身也进行约束了不修改调用对象,所以符合const对象要求,但是非const成员函数,因为他没有加const进行修饰 所以可以对调用对象进行修改 这将违背const对象的意愿,编译器是不允许这么做的。

然后 上面代码中出现的 static const int SIZE = 5;这是在类中定义常量的一种方式,还有一种方式是通过enum定义枚举常量,static也是一种修饰符。

static const 和enum定义的常量一个主要区别就是 static const 是分配存储空间的,而enum定义的不分配,所以static const常量是可以对其进行取地址的,而enum则不允许!

在某些东西声明为const还可以帮助编译器进行侦测错误用法 在这里就不挨个讲述了。

写这篇文章主要是为了整理好后帮助记忆,因为const有很多种用法,稍有不慎就可能导致错误,当然掌握好了const的用法也会对编程有很大的帮助,还有就是为了帮助其他对const不是很了解的人,最后如果文章中写的有哪些问题的话,也麻烦指出来,共同进步,非常感谢!

原创粉丝点击