C++中的const成员函数(函数声明后加const,或称常量成员函数)用法详解

  http://blog.csdn.net/gmstart/article/details/7046140缓存

在C++的类定义里面,能够看到相似下面的定义:函数

01 class List {
02 private:
03      Node * p_head;
04      int length;
05      ……
06 Public:
07      int GetLength () const;
08      bool GetNodeInfo(const int index,Node & buffer) const {…… }
09      bool DeleteNode(const int index);
10      …………
11 }

能够看到,在GetLength和GetNodeInfo两个成员函数的参数列表后面出现了一个const。这个const指明了这个函数不会修改该类的任何成员数据的值,称为常量成员函数。
对于const函数的外部定义,也不能忘记书写const限定符,以下面给出GetLength函数(指返回链表的长度)的定义:spa

1 int List::GetLength() const //这里依然不能忘记const
2 {
3      Return length;
4 }

若是在const成员函数的定义中出现了任何修改对象成员数据的现象,都会在编译时被检查出来,如:.net

1 int List::GetLength() const
2 {
3      Return length++; //错误!
4 }

const成员函数存在的意义在于它能被const常对象调用。咱们都知道,在定义一个对象或者一个变量时,若是在类型前加一个const,如const int x;,则表示定义的量为一个常量,它的值不能被修改。可是建立的对象却能够调用成员函数,调用的成员函数颇有可能改变对象的值,好比下面这段程序:code

1 const List myList;
2 myList.DeleteNode(3); //错误,DeleteLength是非const成员函数

显然调用DeleteNode这个成员函数删除一个链表结点后,颇有可能改变对象中length(链表长度)这个值,这不符合const对象的规定。可是,若是不容许const对象调用任何成员函数又是很是不合理的。因而,咱们把那些确定不会修改对象的各个属性值的成员函数加上const说明符,这样,在编译时,编译器将对这些const成员函数进行检查,若是确实没有修改对象值的行为,则检验经过。之后,若是一个const常对象调用这些const成员函数的时候,编译器将会容许。好比:orm

1 const List myList;
2 myList.GetLength(); //正确,GetLength是const常函数,它返回链表长度,的确没有改变
3 //属性值的行为,被检验经过

你可能会问,为何不在一个const常对象调用成员函数的时候再进行检查呢?若是被调用的函数会改变对象的属性值,则当即打住就是了。这样就不用麻烦地在成员函数后面加const限定符了。然而,这无疑会大大增长编译时间。考虑下面这段代码:对象

1 const List MyList;
2 MyList.GetLength();
3 ……
4 MyList.GetLength();
5 ……

这段代码中,GetLength被调用了两次,可是编译时却也要检查两次,倘使一个成员函数被调用屡次,那么他将在每次调用的时候都会被检查。这显然大大不利。而若是在定义类的时候加上const限定符对常函数加以标记,那么编译器只是检查一次就好,在const对象调用成员函数时,const函数将会被直接放行。因此,C++采起了const限定符描述常函数方案而摈弃了后者。因此,即便一个函数没有修改对象值的行为,若是没有加上const限定符说明是常函数,那么const对象依然不能调用它。
然而,有些时候,咱们却必需要让const函数具备修改某个成员数据值的能力。好比一些内部的状态量,对外部用户无所谓,可是对整个对象的运行却大有用处,如支持缓存的技术。遇到这种问题,咱们能够把一个成员数据定义为mutable(多变的),它表示这个成员变量能够被const成员函数修改却不违法。好比下面定义了一个is_valid类成员:blog

01 class List
02 {
03 private:
04      ……
05      mutable bool is_valid;
06      ……
07 public:
08       bool CheckList() const
09      {
10           if(length >= 1) then return is_valid =true;
11           else return is_valid = false//正确!
12       };

这样,即便像CheckList这样的const成员函数修改它也是合法的。
但须要注意的时,不可滥用mutabe描述符,若是在某个类中只有少数一部分是被容许const常量函数修改的,使用mutable是再合适不过的。若是大部分数据都定义为mutable,那么最好将这些须要修改的数据放入另外一个独立的对象里,并间接地访问它。ip