可变数据成员:

有时我们希望能修改某个类的数据成员,即使是在一个 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. 密码生成工具Cupp

    Cupp可根据已知信息生成相应的字典,用来爆破很有帮助 首先先安装一下cupp 命令:apt-get install cupp 参数说明: -v查看cupp版本号 -h 查看参数列表 -l 从gith ...

  2. springboot成神之——RestTemplate访问Rest

    本文介绍RestTemplate访问Rest demo package com.springlearn.learn; import java.util.Arrays; import org.sprin ...

  3. Python 正则表达式之选择

    In [4]: import re In [5]: re.findall(r"\d+","jjj1234mm222")Out[5]: ['1234', '222 ...

  4. div+css 左右两列自适应高度 ,以及父级div也跟着自适应子级的高度(兼容各大浏览器)

    <style type="text/css" media="screen"> <!-- #main {width:500px;_height: ...

  5. 玩转angularJs——通过自定义ng-model,不仅仅只是input可以实现双向数据绑定

    体验更优排版请移步原文:http://blog.kwin.wang/programming/angularJs-user-defined-ngmodel.html angularJs双向绑定特性在开发 ...

  6. as+bt=1是ab两数互质的充要条件

    [as+bt=1是ab两数互质的充要条件] 充分性,as+bt=1 => (a,b)=1: 因为as+bt=1,设c=(a,b),则c整除a和b,所以c整除as+bt,即c整除1,所以c=1,即 ...

  7. java基础之io流总结四:字符流读写

    字符流读写只适用于字符文件. 基本字符流(转换流)读写文件 转换流本身是字符流,但是实例化的时候传进去的是一个字节流,所以叫做转换流 InputStreamReader isr = new Input ...

  8. 转-使用wifi调试程序

    转自:http://www.cnblogs.com/sunzhenxing19860608/archive/2011/07/14/2106492.html 数据线丢了,不想花钱去买,在网上看了看,an ...

  9. opennebula 对接创建模板参数

    { "id": 8, "name": "c5d1390c-1930-45a5-a686-5cef38b319d7", "displ ...

  10. Linux中IO监控命令的使用分析

    一篇不错的有关linux io监控命令的介绍和使用. 1.系统级IO监控 iostat iostat -xdm 1    # 个人习惯 %util         代表磁盘繁忙程度.100% 表示磁盘 ...