const学习(续)
续接上一篇《C++ const学习》
const与成员函数
之前说到了const修饰成员函数本身。
- const成员函数不能修改对象成员值
- 对于const或者费const对象都可以调用const成员函数,而非const成员函数则只能对非const对象调用
那现在就有三个问题:
- const能否修饰非成员函数?
- const修饰成员函数能否和static一起使用?
- const函数中是否可以修改static成员的值?
- 在实际情况中需要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学习(续)的更多相关文章
- yield学习续:yield return迭代块在Unity3D中的应用——协程
必读好文推荐: Unity协程(Coroutine)原理深入剖析 Unity协程(Coroutine)原理深入剖析再续 上面的文章说得太透彻,所以这里就记一下自己的学习笔记了. 首先要说明的是,协程并 ...
- ES6 let const学习
1.let命令:用法类似于var,但是所声明的变量,只在let命令所在的代码块有效. 例:var a = [ ]; for(var i=0;i<10;i++){ a[ i ] = functio ...
- const 学习笔记
#include<stdlib.h> #include<iostream> using namespace std; int main(){ // const 仅仅起到是否为常 ...
- 树莓派 -- i2c学习 续(1) DeviceTree Overlay实例化rtc
上文中讨论了通过sysfs来实例化i2c设备 (rtc ds3231) https://blog.csdn.net/feiwatson/article/details/81048616 本文继续看看如 ...
- C++ const学习
概念 const就是为了直接表达“不变化的值”这一概念.也就是说该值只可读,不可直接写. 由于不可以修改,所以const常量在声明的时候必须初始化 const int a; //error exter ...
- CSS定位走一波(定位学习续)
又是新的一周过去了,时间到了,春天绿了,关于HTML5的学习进步了,今天博客更新一些CSS定位的内容,小的一些细节也要牢记,方便做一个更完美的项目. 如何让垂直方向居中,解决方式:在父元素添加over ...
- 委托学习续:Action、Func和Predicate
我们先看一个上一章的委托的例子: using System; using System.Collections.Generic; using System.Linq; using System.Tex ...
- html 标签学习(续)
一.基础标签补充 1.div 标签和span标签 (没有特别的样式,常用) div标签用来定义一个块级元素,并无实际的意义.主要通过CSS样式为其赋予不同的表现. span标签用来定义内联(行内)元素 ...
- Kubernetes学习续之一键部署kubeadm
1.Kubernetes的架构和组件,在部署时,它的每一个组件都是一个需要被执行的.单独的二进制文件,所以不难想象,SaltStack这样的运维工具或由社区维护的脚本的功能,就是要把这些二进制文件传输 ...
随机推荐
- javascript 时间格式(很方便的原生函数)
原文:http://www.cnblogs.com/yjf512/p/3796229.html --------------------- <html xmlns="http://ww ...
- 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 ...
- LeetCode 之 Longest Valid Parentheses(栈)
[问题描写叙述] Given a string containing just the characters '(' and ')', find the length of the longest v ...
- poj3511--A Simple Problem with Integers(线段树求和)
A Simple Problem with Integers Time Limit: 5000MS Memory Limit: 131072K Total Submissions: 60441 ...
- boost::mpl::eval_if的使用方法
近期看boost的时候总是遇见这个eval_if,不知道啥意思,就没法看下去了,比方 前篇文章boost::serialization 拆分serialize函数分析时就出现这样一段代码: templ ...
- 【每日算法】排序算法总结(复杂度&稳定性)
一.插入排序:稳定,时间复杂度O(n^2) 想象你在打扑克牌,一開始左手是空的,接着右手開始从桌上摸牌,并将其插入到左手的一把牌中的正确位置上.为了找到这个正确位置,我们须要从右到左将它与手中的牌比較 ...
- java创建线程的三种方式及其对照
Java中创建线程主要有三种方式: 一.继承Thread类创建线程类 (1)定义Thread类的子类.并重写该类的run方法,该run方法的方法体就代表了线程要完毕的任务.因此把run()方法称为运行 ...
- canvas.clipPath canvas.clipRect() 无效的原因
今天发现有些机型不能做到像QQ 透明截图那样的功能,本来能够的.一看是部分机器所有都是灰色半透明遮挡住了,没中间的透明效果,. 并且我不是通过遮挡,我是採用 裁剪的方式,至于裁剪代码百度有相关知识,具 ...
- 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 ...
- [NOI 2014] 起床困难综合征
[题目链接] https://www.lydsy.com/JudgeOnline/problem.php?id=3668 [算法] 从高位向低位贪心即可 时间复杂度 : O(30N) [代码] #in ...