可变数据成员:

有时我们希望能修改某个类的数据成员,即使是在一个 const 成员函数内。可以通过在变量的声明中加入 mutable 关键字来声明一个可变数据成员。mutable 是为突破 const 的限制而设置的。被 mutable 修饰的变量将永远处于可变状态中,即使是在一个 const 成员函数中:

 #include <iostream>
using namespace std; class gel{
private:
mutable size_t access_ctr; public:
gel() = default;
gel(const int &x):access_ctr(x){}
// ~gel(); void out_put() const{
cout << access_ctr << endl;
} void some_member(void) const{
++access_ctr;
}
}; int main(void){
const gel x();
x.out_put();//输出1
x.some_member();
x.out_put();//输出2
x.some_member();
x.out_put();//输出3
return ;
}

关于 mutable 关键字存在的必要性:https://www.zhihu.com/question/64969053/answer/226383958

基于 const 的重载:

 #include <iostream>
using namespace std; class gel{
private:
int x; public:
gel() = default;
gel(int val): x(val){} const gel &display(std::ostream &os) const{
std::cout << x;
return *this;
} gel &count(void){
x++;
return *this;
}
}; int main(void){
gel x();
x.display(cout);
x.count();
// x.display(cout).count();//错误:display 返回的是一个 const 对象,而 count 不是常量函数
return ;
}

一般来说像 x.display(cout); 与 x.count(); 应该是要可以写成 x.display(cout).count();的形式的。但这个代码中 display 返回的是一个 const 对象,所以后者显然是错误的。这是我们代码写的不合理,应该尽量避免写出这样的代码。我们可以通过重载解决这个问题:

 #include <iostream>
using namespace std; class gel{
private:
int x; public:
gel() = default;
gel(int val): x(val){} gel &display(std::ostream &os){
do_display(os);
// os << x;//在代码比较短的时候这样写也一样,不过要是代码量大的话显然要多写不少代码
return *this;
} const gel &display(std::ostream &os) const{
do_display(os);
// os << x;
return *this;
} gel &count(void){
x++;
return *this;
} private:
void do_display(std::ostream &os) const{
os << x;
}
}; int main(void){
gel x();
x.display(cout).count();
return ;
}

这里我们通过调用 display 的对象是否为常量来决定调用哪个 display 函数。需要注意的是这里是通过底层 const 来区分重载函数的(形参会忽略顶层 const),若调用 display 的对象是 const,那么隐式传递的 this 指针具有底层 const,反之则没有。

调用 display 的是非常量的话,display 返回的也是一个非常量对象,此时 x.display(cout).count();顺利执行;

调用 display 的是常量的话, display 返回的也是一个常量对象,此时 x.display(cout).count();报错。

显然,这个代码中的 x.display(cout).count();与 x.display(cout);x.count();是完全等价的。

类4(可变数据成员/基于const的重载)的更多相关文章

  1. static数据成员与const数据成员的定义与初始化

    三种数据类型的初始化 1.static int a 的初始化 const int a 的初始化 static const int a的初始化 三种初始化方式 在类外初始化 在构造函数中通过初始化列表初 ...

  2. C++ 学习之函数重载、基于const的重载

    函数重载 函数重载的定义是:在相同的作用域中,如果函数具有相同名字而仅仅是形参表不同,此时成为函数重载.注意函数重载不能基于不同的返回值类型进行重载. 注意函数重载中的"形参表"不 ...

  3. Cocos2d-x 3.1.1 学习日志3--C++ 初始化类的常量数据成员、静态数据成员、常量静态数据成员

    版权声明:本文为博主原创文章,未经博主同意不得转载. https://blog.csdn.net/u011292087/article/details/37598919 有关const成员.stati ...

  4. 编写一个矩形类,私有数据成员为矩形的长( len)和宽(wid),wid设置为0,有参构造函数设置和的值,另外,类还包括矩形的周长、求面积、取矩形的长度、取矩形的长度、取矩形的宽度、修改矩形的长度和宽度为对应的形参值等公用方法。

    class Rectangle { private double len, wid; public Rectangle()//求矩形周长 { len = 0; wid = 0; } public Re ...

  5. C++类中静态数据成员MAP如何初始化

    conv_xxx.hpp class convolution { ... ... typedef std::map<int, std::string> ConvDtMap; static ...

  6. 如何导出标准模板库(STL)类的实例化和包含STL类对象数据成员的类

    本文翻译自 https://support.microsoft.com/zh-cn/help/168958/how-to-export-an-instantiation-of-a-standard-t ...

  7. 正确理解Widget::Widget(QWidget *parent) :QWidget(parent)这句话(初始化列表中无法直接初始化基类的数据成员,所以你需要在列表中指定基类的构造函数)

    最近有点忙,先发一篇我公众号的文章,以下是原文. /********原文********/ 最近很多学习Qt的小伙伴在我的微信公众号私信我,该如何理解下面段代码的第二行QWidget(parent) ...

  8. 转:C语言中的static变量和C++静态数据成员(static member)

    转自:C语言中的static变量和C++静态数据成员(static member) C语言中static的变量:1).static局部变量        a.静态局部变量在函数内定义,生存期为整个程序 ...

  9. C++:用成员初始化列表对数据成员初始化

    1.在声明类时,对数据成员的初始化工作一般在构造函数中用赋值语句进行. 例如: class Complex{ private: double real; double imag; public: Co ...

随机推荐

  1. js操作一般文件和csv文件

    js操作一般文件和csv文件 将文本文件读成字符串 <input type="file" id="upload"> document.getElem ...

  2. Python下OS模块重命名方法renames

    在python中有很多强大的模块,其中我们经常要使用的就是OS模块,OS模块提供了超过200个方法来供我们使用,并且这些方法都是和数据处理相关的,这里介绍下重命名这个方法. OS的重命名方法是os.r ...

  3. 浅层神经网络 反向传播推导:MSE softmax

    基础:逻辑回归 Logistic 回归模型的参数估计为什么不能采用最小二乘法? logistic回归模型的参数估计问题不能“方便地”定义“误差”或者“残差”. 对单个样本: 第i层的权重W[i]维度的 ...

  4. 【知识碎片】 Linuxb 篇

    3.登录mysql 开启MySQL服务后,使用MySQL命令可以登录.一般使用mysql -uroot -p即可.如果数据库不是本机,则需要加参数,常用参数如下:1,-h,指定ip地址,默认为loca ...

  5. LINQ GroupBy 查询数据赋给select

    roles.GroupBy(a => new { a.SubjectID,a.SubjectName}).Select(p => new SelectListItem() { Value ...

  6. java基础之集合长度可变的实现原理

    首先我们要明白java中的集合Collection,List,ArrayList之间的关系: ArrayList是具体的实现类,实现了List接口 List是接口,继承了Collection接口 Li ...

  7. 30-懒省事的小明(priority_queue)

    http://acm.nyist.edu.cn/JudgeOnline/problem.php?pid=55 懒省事的小明 时间限制:3000 ms  |  内存限制:65535 KB 难度:3   ...

  8. Docker学习笔记_安装和使用Python

    一.实验目标 在Docker里安装Python3.5 二.准备 1.宿主机OS:Win10 64 2.虚拟机OS:Ubuntu18.04 3.操作账号:Docker 二.安装过程 1.搜索Python ...

  9. sencha警告:[WARN][Anonymous] [Ext.Loader] Synchronously loading 'Ext.field.Text'

    chrome开发者工具下提示: [WARN][Anonymous] [Ext.Loader] Synchronously loading 'Ext.field.Text'; consider addi ...

  10. 如何实现字符串的翻转,不用php库函数翻转字符串