续接上一篇《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 = ;   //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#转过来的,不习惯运用宏定义常量

const学习(续)的更多相关文章

  1. yield学习续:yield return迭代块在Unity3D中的应用——协程

    必读好文推荐: Unity协程(Coroutine)原理深入剖析 Unity协程(Coroutine)原理深入剖析再续 上面的文章说得太透彻,所以这里就记一下自己的学习笔记了. 首先要说明的是,协程并 ...

  2. ES6 let const学习

    1.let命令:用法类似于var,但是所声明的变量,只在let命令所在的代码块有效. 例:var a = [ ]; for(var i=0;i<10;i++){ a[ i ] = functio ...

  3. const 学习笔记

    #include<stdlib.h> #include<iostream> using namespace std; int main(){ // const 仅仅起到是否为常 ...

  4. 树莓派 -- i2c学习 续(1) DeviceTree Overlay实例化rtc

    上文中讨论了通过sysfs来实例化i2c设备 (rtc ds3231) https://blog.csdn.net/feiwatson/article/details/81048616 本文继续看看如 ...

  5. C++ const学习

    概念 const就是为了直接表达“不变化的值”这一概念.也就是说该值只可读,不可直接写. 由于不可以修改,所以const常量在声明的时候必须初始化 const int a; //error exter ...

  6. CSS定位走一波(定位学习续)

    又是新的一周过去了,时间到了,春天绿了,关于HTML5的学习进步了,今天博客更新一些CSS定位的内容,小的一些细节也要牢记,方便做一个更完美的项目. 如何让垂直方向居中,解决方式:在父元素添加over ...

  7. 委托学习续:Action、Func和Predicate

    我们先看一个上一章的委托的例子: using System; using System.Collections.Generic; using System.Linq; using System.Tex ...

  8. html 标签学习(续)

    一.基础标签补充 1.div 标签和span标签 (没有特别的样式,常用) div标签用来定义一个块级元素,并无实际的意义.主要通过CSS样式为其赋予不同的表现. span标签用来定义内联(行内)元素 ...

  9. Kubernetes学习续之一键部署kubeadm

    1.Kubernetes的架构和组件,在部署时,它的每一个组件都是一个需要被执行的.单独的二进制文件,所以不难想象,SaltStack这样的运维工具或由社区维护的脚本的功能,就是要把这些二进制文件传输 ...

随机推荐

  1. javascript 时间格式(很方便的原生函数)

    原文:http://www.cnblogs.com/yjf512/p/3796229.html --------------------- <html xmlns="http://ww ...

  2. modem&NIC&sound card

    Rate: Phone:8 k hz   radio:22050 hz Digital Video camcorder; miniDV; DAT LP mode:32 k hz Audio CD MP ...

  3. LeetCode 之 Longest Valid Parentheses(栈)

    [问题描写叙述] Given a string containing just the characters '(' and ')', find the length of the longest v ...

  4. poj3511--A Simple Problem with Integers(线段树求和)

    A Simple Problem with Integers Time Limit: 5000MS   Memory Limit: 131072K Total Submissions: 60441   ...

  5. boost::mpl::eval_if的使用方法

    近期看boost的时候总是遇见这个eval_if,不知道啥意思,就没法看下去了,比方 前篇文章boost::serialization 拆分serialize函数分析时就出现这样一段代码: templ ...

  6. 【每日算法】排序算法总结(复杂度&amp;稳定性)

    一.插入排序:稳定,时间复杂度O(n^2) 想象你在打扑克牌,一開始左手是空的,接着右手開始从桌上摸牌,并将其插入到左手的一把牌中的正确位置上.为了找到这个正确位置,我们须要从右到左将它与手中的牌比較 ...

  7. java创建线程的三种方式及其对照

    Java中创建线程主要有三种方式: 一.继承Thread类创建线程类 (1)定义Thread类的子类.并重写该类的run方法,该run方法的方法体就代表了线程要完毕的任务.因此把run()方法称为运行 ...

  8. canvas.clipPath canvas.clipRect() 无效的原因

    今天发现有些机型不能做到像QQ 透明截图那样的功能,本来能够的.一看是部分机器所有都是灰色半透明遮挡住了,没中间的透明效果,. 并且我不是通过遮挡,我是採用 裁剪的方式,至于裁剪代码百度有相关知识,具 ...

  9. codeforces 963B Destruction of a Tree

    B. Destruction of a Tree time limit per test 1 second memory limit per test 256 megabytes input stan ...

  10. [NOI 2014] 起床困难综合征

    [题目链接] https://www.lydsy.com/JudgeOnline/problem.php?id=3668 [算法] 从高位向低位贪心即可 时间复杂度 : O(30N) [代码] #in ...