条款3 尽可能使用const
const允许你指定一个语义约束,也就是指定一个不该被改动的对象。
需要指明一下
void f1(const Widget* pw);
void f2(Widget const* pw);
这两种的写法含义相同。
函数返回一个常量值,往往可以降低因客户使用错误而造成的意外,而且很安全、高效,举个例子。
class Rational{...}; //有理数
const Rational operator* (const Rational& lhs, const Rational& rhs);
比如就可以使用以下使用方式:
Rational a,b,c;
(a * b) = c;
如果两个成员函数如果只是常量性不同,可以被重载
#include <iostream>
#include <string>
using namespace std;
class TextBlock
{
public:
TextBlock(string str):text(str){}
const char& operator[](size_t pos) const
{
cout << "const"<<endl;
return text[pos];
}
char& operator[](size_t pos)
{
cout << "non - const"<<endl;
return text[pos];
}
private:
string text;
};
int main(int argc, char *argv[])
{
TextBlock tb("hello");
const TextBlock ctb("world");
cout << tb[0] <<endl;
cout << ctb[0] <<endl;
return 0;
}
//打印结果
non - const
h
const
w
带const修饰的成员函数不可以修改成员变量
class CTextBlock
{
public:
size_t len() const
{
if(!m_bLenIsValid)
{
//错误不可以修改
//CTextBlock::m_textLen' in read-only object
//CTextBlock::m_bLenIsValid' in read-only object
m_textLen = strlen(m_pText);
m_bLenIsValid = true;
}
}
private:
char* m_pText;
size_t m_textLen; //最近一次计算的文本区域长度
bool m_bLenIsValid; //目前长度是否有效
};
解决办法就是使用mutable(可变的)修饰。
mutable size_t m_textLen; //最近一次计算的文本区域长度
mutable bool m_bLenIsValid; //目前长度是否有效
避免const和non-const成员函数中的重复
可以看出的我们上面的const函数const char& operator[](size_t pos) const和非const函数中有很多代码重复。
我们可以使用转型的方法:
class TextBlock
{
public:
...
const char& operator[](size_t pos) const
{
...
return text[pos];
}
char& operator[](size_t pos)//调用const op[]
{
...
//将op[]返回值的const转除为*this加上const调用const op[]
return const_cast<char&>(
//这里必须指明调用的是const op[],否则将会无限递归。
//将*this从TextBlock&转成const TextBlock&
static_cast<const TextBlock&>(*this)[pos]
)
}
private:
string text;
};
重点
- 将某些东西声明为const可帮助编译器侦测出错误的用法。
- 假如当const和non-const成员函数有着相同的用法时,non-const的成员函数调用const版本可以避免代码重复