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 constness\bitwise 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#转过来的,不习惯运用宏定义常量

 

posted @ 2013-07-16 17:23  haox  阅读(1040)  评论(1编辑  收藏  举报