类4(可变数据成员/基于const的重载)

可变数据成员:

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

 1 #include <iostream>
 2 using namespace std;
 3
 4 class gel{
 5 private:
 6     mutable size_t access_ctr;
 7
 8 public:
 9     gel() = default;
10     gel(const int &x):access_ctr(x){}
11     // ~gel();
12
13     void out_put() const{
14         cout << access_ctr << endl;
15     }
16
17     void some_member(void) const{
18         ++access_ctr;
19     }
20 };
21
23 int main(void){
24     const gel x(1);
25     x.out_put();//输出1
26     x.some_member();
27     x.out_put();//输出2
28     x.some_member();
29     x.out_put();//输出3
30     return 0;
31 }

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

基于 const 的重载:

 1 #include <iostream>
 2 using namespace std;
 3
 4 class gel{
 5 private:
 6     int x;
 7
 8 public:
 9     gel() = default;
10     gel(int val): x(val){}
11
12     const gel &display(std::ostream &os) const{
13         std::cout << x;
14         return *this;
15     }
16
17     gel &count(void){
18         x++;
19         return *this;
20     }
21 };
22
23 int main(void){
24     gel x(0);
25     x.display(cout);
26     x.count();
27     // x.display(cout).count();//错误:display 返回的是一个 const 对象,而 count 不是常量函数
28     return 0;
29 }

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

 1 #include <iostream>
 2 using namespace std;
 3
 4 class gel{
 5 private:
 6     int x;
 7
 8 public:
 9     gel() = default;
10     gel(int val): x(val){}
11
12     gel &display(std::ostream &os){
13         do_display(os);
14         // os << x;//在代码比较短的时候这样写也一样,不过要是代码量大的话显然要多写不少代码
15         return *this;
16     }
17
18     const gel &display(std::ostream &os) const{
19         do_display(os);
20         // os << x;
21         return *this;
22     }
23
24     gel &count(void){
25         x++;
26         return *this;
27     }
28
29 private:
30     void do_display(std::ostream &os) const{
31         os << x;
32     }
33 };
34
35 int main(void){
36     gel x(0);
37     x.display(cout).count();
38     return 0;
39 }

这里我们通过调用 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();是完全等价的。

原文地址:https://www.cnblogs.com/geloutingyu/p/8087928.html

时间: 2024-08-08 20:36:36

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

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

有关const成员.static成员.const static成员的初始化: 1.const成员:只能在构造函数后的初始化列表中初始化 2.static成员:初始化在类外,且不加static修饰 3.const static成员:类只有唯一一份拷贝,且数值不能改变.因此,可以在类中声明处初始化,也可以像static在类外初始化 #include <iostream> using std::cout; using std::endl; class base { public: base(int

C++类中常量数据成员和静态数据成员初始化

常量数据成员初始化原则: 在每一个构造函数的初始化列表中初始化 静态数据成员初始化原则: 类内声明,类外初始化(因为它是属于类的,不能每构造一个对象就初始化一次) // test_max.cpp : 定义控制台应用程序的入口点. #include "stdafx.h" #include <iostream> #include <vector> using namespace std; class A { public: A(int i):a(0) {} A():

c++类中对数据成员进行初始化和赋值的区别

在c++中定义一个类 ,对于构造函数 我们经常是这么写的: class test { public: test(int n_x , int n_y) { x = n_x; y = n_y; } private: int x , y; }; 这中写法虽然是合法的但比较草率 在构造函数 test(int n_x , int n_y)中 , 我们这样实际上不是对数据成员进行初始化 , 而是进行赋值. 正确的是初始化应该是这样的: class test { public: test() {} test(

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

三种数据类型的初始化 1.static int a 的初始化 const int a 的初始化 static const int a的初始化 三种初始化方式 在类外初始化 在构造函数中通过初始化列表初始化 在声明的同时初始化 一.static数据成员 静态成员:静态类中的成员加入static修饰符,即是静态成员.可以直接使用"类名.静态成员名"访问此静态成员,因为静态成员存在于内存,非静态成员需要实例化才会分配内存,所以静态成员函数不能访问非静态的成员..因为静态成员存在于内存,所以非

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

函数重载 函数重载的定义是:在相同的作用域中,如果函数具有相同名字而仅仅是形参表不同,此时成为函数重载.注意函数重载不能基于不同的返回值类型进行重载. 注意函数重载中的"形参表"不同,是指本质不同,不要被一些表象迷惑.main函数不能被重载. 下面三组定义本质是相同的,不是重载: 1)int sum (int &a); 和 int sum (int &); 2)  int sum (int a) 和 int sum (const int a); 3)typedef in

类的静态数据成员初始化问题

1. 静态数据成员在类声明中声明,在包含类方法的文件中初始化.初始化时使用作用域运算符来指出静态成员所属的类.但如果静态成员是整形const或枚举型const,则可以在类声明中初始化. C++ primer plus P426-P427类静态成员的声明和初始化 //strnbad.h class StringBad { private: static int num_strings; … }; //strnbad.cpp int StringBad::num_strings = 0; 不能在类声

在另一个类中做数据成员的对象,可以先不初始化

class A { B b; } 因为在创建A类的时候,会先调用A的构造函数,同时对B类中的b对象调用他的构造函数 下面测试代码 class A { public: int a; A(int x) :a(x){}; }; class B:public A { private: A b; public: B(int x, int y) :A(x), b(y){} void display() { cout << a << endl << b.a << endl

定义一个Circle类,有数据成员Radius(半径)

//成员函数GetArea(),计算圆的面积,构造一个Circle的对象进行测试. #include <iostream> using namespace std; #define PI 3.1415926 class Circle { public : Circle() {}; Circle(double r) { Radius=r; } double GetArea() { return PI*Radius*Radius; } private: double Radius; }; int

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

class Rectangle { private double len, wid; public Rectangle()//求矩形周长 { len = 0; wid = 0; } public Rectangle(int l, int w)//求矩形面积 { len = l; wid = w; } public double perimeter()//求周长 { return ((len + wid) * 2); } public double area()//求面积 { return (le