条款三:尽可能地使用const
首先,我们需要知道const的作用:const是C++中的关键字,它允许我们指定一个语义的约束。
const分为两种:
1、顶层const:
顶层const的语法位置处于指针的右边,其作用是表明该指针不可指向其他对象,即:指针的自身是一个常量。
eg:char * const
2、底层const
底层const的语法位置处于指针的左边,其作用是表明该指针所指向的内容不可改变,即:被指物是一个常量。
在STL的迭代器中,迭代器的作用就类似与一个指针p*。所以当我们对一个迭代器使用const声明时,就等于对这个p*指针声明为const,即:p* const,此时,const位于*的右边,所以表明指针本身是一个常量,不可指向别的对象。那当我们想要使得迭代器中指向的内容不被修改应该怎么样呢?此时我们就需要使用迭代器中的const_iterator;const_iterator的作用即类似于const T*,这个时候,const位于*的左边,表示,该指针所指向的内容不可被修改。
二、const成员函数
在这一条款中,我知道了,两个成员函数如果只是常量性不同,可以被重载。
在此前,只是知道重载的三大条件是:
1、形参的数量不同
2、形参的类型不同
3、形参的顺序不同
注:返回值的类型不同并不能重载。
以下的这段代码是仅通过返回值的类型进行重载,但是可以知道这是错误的做法。
#include <iostream>
int override_func(int para)
{
std::cout << "fun:" << para << std::endl;
return 0;
}
double override_func(int para)
{
std::cout << "fun:" << para << std::endl;
return 0;
}
所以,人们很容易忽略一点:两个成员函数如果只是常量性不同,可以被重载。
class test
{
public:
int& test_func(int position) const
{
return position;
}
int& test_func(int position)
{
return position;
}
protected:
private:
};
我们可以看到以上的这段代码,在参数列表上是完全一样的,但是由于两个成员函数的常量型的不同,它们可以被成功重载。
关于const成员函数的两个流派:bitwise constness 和logical constness
Bitwise constness(简称BC) :成员函数只有在不更改对象内的任何一个成员变量(static 除外)时才可以说是const。也就是说成员函数不能修改对象内的任何bit。这正是C++对常量性的的定义,因此const成员函数不可以修改任何non-static成员变量。
但是有一种例外情况:
假设,有一个成员函数修改了对象内的指针所指物,但是只有指针是对象成员,而指针所指物并非对象成员,这样也可以通过编译。
为了方便理解,可以参考下图:
即,若指针*p指向了a,但是a的内容改变了(从123变成1234),并不会违反bitwise constness 的法则,同样会通过编译。
Logical constness(简称LC): 一个const成员函数可以修改它所处理的成员内的某些bits,但只有在客户端侦测不出的情况下在得如此。
所以,具有的区别就在于,BC是不能改变对象的任何数据,LC是可以改变数据。但是由于C++编译器一般使用BC法则,所以当我们LC法则时,我们需要使用到mutable这个关键字。
mutable:使得即使是在const成员函数中,变量也可以被改变。
总结:
在条款03:尽可能使用const中学到的:
1、顶层和底层的const自然不用多说,更加熟悉了
2、const成员函数的重要特性