zoukankan      html  css  js  c++  java
  • const学习(续)

      续接上一篇《C++ const学习》

    const与成员函数  

      之前说到了const修饰成员函数本身。

    1. const成员函数不能修改对象成员值
    2. 对于const或者费const对象都可以调用const成员函数,而非const成员函数则只能对非const对象调用

      那现在就有三个问题:

    1. const能否修饰非成员函数?
    2. const修饰成员函数能否和static一起使用?
    3. const函数中是否可以修改static成员的值?
    4. 在实际情况中需要const成员函数修改没个成员的值呢?如果有,该如何处理?
      class ClassB
      {
      public:
          static int s_a;
          string a;
          static void funB() const;    //2.??
          void funC() const
          {
              s_a = 1;    //3.??
              a = "xx";    //4.??
          }
      };

      对于问题一,假设非成员函数可以被const修改,那是要限定什么值不能修改呢?全局?而且这个const函数是对谁提供的呢?好像我们并不能找到合适的答案。所以funA(),编译时不通过,error:非成员函数不允许使用限定符。也就是说在C中不存在const限定函数这种情形。

      问题二其实和问题一是一样的,static成员函数属于类,并不属于某个对象。同样编译给出的error: 静态成员函数上不允许修饰符。

      问题三和二一样,可以修改static成员值。

      对于问题四,就要先看实际中有没有这种可能。暂时没想到合适的例子,就直接copy《The c++ Programming Language》书上的缓存了。在经常读取某些复杂的数据结构时,如将对象转化为string,为了提高效率,就用到了缓存,这个转换的过程ToString()只可能对缓存cache做修改,而不修改对象的其他成员值。此时就存在了ToString() const修改cache这个值。

      这里就分为物理常量(physical constnessitwise constness)和逻辑常量(logical constness)。物理常量其实就是const常量性的定义,因此不可修改对象的任何成员的值。而逻辑常量就是问题四中那种形式,客户端侦测不出可以修改的变量,如cache。

      此时可以将const转化为non-const,运用const_cast  

    class ClassB
    {
    public:
        string a;
        void funC() const
        {
            ClassB * nonConstb=    const_cast<ClassB *>(this);
            nonConstb->a="xx";
    
            cout<<"nonConstb:"<<nonConstb<<endl;
            cout<<"this:"<<this<<endl;
        }
    };
    
    int _tmain(int argc, _TCHAR* argv[])
    {
    
        ClassB cb;
        cb.funC();
        cout<<cb.a.c_str();
    }

      运行结果为:  

      nonConstb:0015FB58
      this:0015FB58
      xx
      请按任意键继续. . . 

      通过代码及运行结果可以看出:

    • 非const对象隐式的转化为const对象,再调用const成员函数
    • const_cast类型转换时,对象地址不变,将在const成员函数中将const对象指针this,转化为non-constd对象指针nonConstb

      《Effective c++》中提到的转型是一个糟糕的想法,如条款27(目前还没看到这里,先不详谈,个人认识所有的转型都有信息的丢失,且有些是不可逆的)

      mutable释放掉non-static成员变量的bitwise constness约束:
      

    class ClassB
    {
    public:
        string a;
        mutable string b;
        void funC() const
        {        
            b="yyy";
        }
    };
    int _tmain(int argc, _TCHAR* argv[])
    {
    
        ClassB cb;
        cb.funC();
         cout<<cb.b.c_str()<<endl;
    }

      输出结果:yyy

      ok,到目前为止,把关于const的只是整理学习了下。

      在实际代码中个人偏好是:

    • 能用const就一定要用const。因为用了不会错,不用可能出错,而且编译器可以帮助检出某些人为的疏忽错误
    • const可以帮助软件的设计与代码书写着沟通。个人最喜欢的就是将可为const的函数参数一定限定为const,由于以前在做C#的时候一直没找到一个好的方法,限定函数内部不要修改传过来的参数值
    • 减少代码中的各种文字常量,与一些莫名其妙的数值与字串
    • 还有个原因,个人是从C#转过来的,不习惯运用宏定义常量
  • 相关阅读:
    九.Protobuf3特殊类型
    八.Protobuf3更新消息类型(添加新的字段)
    七.Protobuf3 嵌套类型
    六.Protobuf3引入其他.proto文件
    五.Protobuf3 枚举
    四.Protobuf3 缺省值
    VC 在调用main函数之前的操作
    Windows下的代码注入
    C 堆内存管理
    VC++ 崩溃处理以及打印调用堆栈
  • 原文地址:https://www.cnblogs.com/haox/p/3187617.html
Copyright © 2011-2022 走看看