可变数据成员:

有时我们希望能修改某个类的数据成员,即使是在一个 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. C Primer Plus学习笔记(九)- 数组和指针

    数组 数组由数据类型相同的同一系列元素组成 需要使用数组时,通过声明数组告诉编译器数组中内含多少元素和这些元素的类型 普通变量可以使用的类型,数组元素都可以用 float candy[365]; // ...

  2. ansible命令详解

    查看ansible版本 import ansible print(ansible.__version__) 命令参数 -m:要执行的模块,默认为command -a:模块的参数 -u:ssh连接的用户 ...

  3. Location - BOM对象

    Location 对象 Location 对象包含有关当前 URL 的信息. Location 对象是 Window 对象的一个部分,可通过 window.location 属性来访问. 例子 把用户 ...

  4. xcode恢复语法高亮

    [xcode恢复语法高亮] 非常简单,在Organizer中删除derivedData.

  5. java Web 监听器Listener详解

    简介 JavaWeb中的监听器是Servlet规范中定义的一种特殊类,它用于监听web应用程序中的ServletContext.HttpSession和 ServletRequest这三大域对象的创建 ...

  6. MySQL5.7插入中文乱码

    参考: https://blog.csdn.net/kelay06/article/details/60870138 https://blog.csdn.net/itmr_liu/article/de ...

  7. springMVC+spring+mybatis整合(包括文件上传和下载)

    driver=com.mysql.jdbc.Driver url=jdbc:mysql://localhost:3306/test?useUnicode=true&characterEncod ...

  8. spring aop自动代理注解配置之一

    <?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.sp ...

  9. ubuntu 14 编译ARM g2o-20160424

    1. 安装eigen sudo apt-get install libeigen3-dev sudo apt-get install libsuitesparse-dev sudo apt-get i ...

  10. C++ 输出精度和输出小数点位数

    有时候需要调节小数点的精度或者位数 #include<iostream> #include<iomanip> using namespace std; //设置数据精度 set ...