续接上一篇《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. 百度UEditor富文本上传图片

    项目中使用UEditor发现设置图片自定义保存路径会出现<请求后台配置项http错误,上传功能将不能正常使用!错误> /* 上传图片配置项 */ "imageActionName ...

  2. RabbitMQ环境搭建教程收集(待实践)

    先收集,后续再实践. http://blog.csdn.net/zyz511919766/article/details/41896823 http://blog.chinaunix.net/uid- ...

  3. Android GIS开发系列-- 入门季(14)FeatureLayer之范围查询

    Android GIS开发系列-- 入门季(5),这篇文章中,我们知道如何去查找要素.现在有一个需求,查找某点5000米范围的要素,那如何来做呢?首先我们需要在地图上画个5000米半径的圆,然后根据Q ...

  4. json序列化后的是字符串,不是二进制。是字符串!!!确定不是二进制!!!

    1.现有一个自定义对象需要储存到sql数据库中去.这个对象里面属性很多,甚至包含一些元素量打到几十万的List集合属性.本人试着使用JSON序列化这个对象,储存到数据库,报maxjsonlength超 ...

  5. 1076. Forwards on Weibo (30)【树+搜索】——PAT (Advanced Level) Practise

    题目信息 1076. Forwards on Weibo (30) 时间限制3000 ms 内存限制65536 kB 代码长度限制16000 B Weibo is known as the Chine ...

  6. 如何以正确的顺序重新安装驱动程序 | Dell 中国

      购买 支持 社区 我的帐户     购买 支持 社区   如何以正确的顺序重新安装驱动程序 在戴尔笔记本电脑或台式机上手动重新安装Microsoft Windows操作系统后,您还必须以正确的顺序 ...

  7. imx6q GPIO功能的用法

    假如我们要使用扩展口的第11脚EIM_D18. 先在arch/arm/plat-mxc/include/mach/iomux-mx6q.h中找有EIM_18. 能够找到MX6Q_PAD_EIM_D18 ...

  8. MySQL系列:innodb源代码分析之内存管理

    在innodb中实现了自己的内存池系统和内存堆分配系统,在innodb的内存管理系统中,大致分为三个部分:基础的内存块分配管理.内存伙伴分配器和内存堆分配器.innodb定义和实现内存池的主要目的是提 ...

  9. ADB无法启动

    一般就是5037端口被占用,各种手机助手鼓捣的 1.CMD下查看端口是否被占用 netstat -ano|findstr "5037" 截图不上了,我的是820进程,360手机助手 ...

  10. grep 并列查询 效率 且 或

    find / | grep -v python | grep -v xl_ | grep -v xiaole |grep redis [root@hadoop3 ~]# find / | grep - ...