zoukankan      html  css  js  c++  java
  • c++类中const函数与mutable变量的使用方法(转)

    在C++的类定义里面,可以看到类似下面的定义:

    class List {
    private:
         Node * p_head;
         int length;
         ……
    Public:
         int GetLength () const;
         bool GetNodeInfo(const int index,Node & buffer) const {…… }
         bool DeleteNode(const int index);
         …………
    }
     

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

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

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

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

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

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

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

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

    你可能会问,为什么不在一个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类成员:

    class List
    {
    private:
         ……
         mutable bool is_valid;
         ……
    public:
          bool CheckList() const
         {
              if(length >= 1) then return is_valid =true;
              else return is_valid = false; //正确!
          };
     
     

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

    参考资料:《C++ Programming Language 第三版》
    注:本文属知无涯原创,转载请注明出处!

  • 相关阅读:
    Centos 7 zabbix 实战应用
    Centos7 Zabbix添加主机、图形、触发器
    Centos7 Zabbix监控部署
    Centos7 Ntp 时间服务器
    Linux 150命令之查看文件及内容处理命令 cat tac less head tail cut
    Kickstart 安装centos7
    Centos7与Centos6的区别
    Linux 150命令之 文件和目录操作命令 chattr lsattr find
    Linux 发展史与vm安装linux centos 6.9
    Linux介绍
  • 原文地址:https://www.cnblogs.com/maskoff/p/8649125.html
Copyright © 2011-2022 走看看