类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();是完全等价的。

posted @ 2017-12-25 22:34  geloutingyu  阅读(295)  评论(0编辑  收藏  举报