首页 > 代码库 > 条款21: 尽可能使用const

条款21: 尽可能使用const

对指针来说,可以指定指针本身为const,也可以指定指针所指的数据为const,或二者同时指定为const,还有,两者都不指定为const:

char *p              = "hello";          // 非const指针,                                         // 非const数据const char *p        = "hello";          // 非const指针,                                         // const数据char * const p       = "hello";          // const指针,                                         // 非const数据const char * const p = "hello";          // const指针,                                         // const数据

const的一些强大的功能基于它在函数声明中的应用。在一个函数声明中,const可以指的是函数的返回值,或某个参数;对于成员函数,还可以指的是整个函数。


 

类的成员函数后面加 const,表明这个函数不会对这个类对象的数据成员(准确地说是非静态数据成员)作任何改变。

在设计类的时候,一个原则就是对于不改变数据成员的成员函数都要在后面加 const,而对于改变数据成员的成员函数不能加 const。所以 const 关键字对成员函数的行为作了更加明确的限定:有 const 修饰的成员函数(指 const 放在函数参数表的后面,而不是在函数前面或者参数表内),只能读取数据成员,不能改变数据成员;没有 const 修饰的成员函数,对数据成员则是可读可写的。

除此之外,在类的成员函数后面加 const 还有什么好处呢?那就是常量(即 const)对象可以调用 const 成员函数,而不能调用非const修饰的函数。非常量对象可以随意调用const或非const修饰的函数。正如非const类型的数据可以给const类型的变量赋值一样,反之则不成立。

class student{public:    student(){}    student(const string &nm, int sc = 0)        :name(nm), score(sc){}    void set_student(const string &nm, int sc = 0)    {        name = nm;        score = sc;    }    const string &get_name()const    {        return name;    }    int get_score()const    {        return score;     }private:    string name;    int score;};void output(const student &stu){    //正常调用    cout << stu.get_name();    cout << stu.get_score();}

若get_name和get_score没有const修饰,则const student变量不能调用这两个函数

class student{public:    student(){}    student(const string &nm, int sc = 0)        :name(nm), score(sc){}    void set_student(const string &nm, int sc = 0)    {        name = nm;        score = sc;    }    const string &get_name()    {        return name;    }    int get_score()    {        return score;     }private:    string name;    int score;};void output(const student &stu){    //编译出错    cout << stu.get_name();    cout << stu.get_score();}

为什么 get_name() 前面也加 const。如果没有前后两个 const 的话,get_name() 返回的是对私有数据成员 name 的引用,所以通过这个引用可以改变私有成员 name 的值,如

student stu("wang", 85);stu.get_name() = "li";