6.Const
C++用const来定义常数:
//C
#define BUFF_LENGTH 1024
int buffer[BUFF_LENGTH];
//C++
const int BUFF_LENGTH= 1024;
int buffer[BUFF_LENGTH];
这样做的好处是:编译器知道BUFF_LENGTH的名字和类型,这样做也不会给程序的执行上带来额外的开销,如果我们不去使用BUFF_LENGTH的地址的话,编译器也不需要为它们专门申请存储空间。
我们还可以声明一个”指向常量的指针“,来保证指针指向的对象不被改变。记住一点:将某事物声明为const(或者是指向const的指针或者引用)会引起额外的编译期检测,但它并不会导致编译器产生额外的代码。
6.1常量引用参数
//正确但运行缓慢的代码:不必要的Telephone_numberd的拷贝
void dial(Telephone_numberd tn){//...}
//改善后的代码:使用一个常量引用:
void dial(const Telephone_numberd& tn){//...}
改善的代码避免了对输入参数进行复制并在函数返回时摧毁该复制的操作。此处使用const阻止了被调用函数无意中对调用函数中对象的值进行修改。
6.2常量参数和常量指针
如果函数只是同过指针来读取(并不会修改它的内容),在函数声明时,我们应该讲该参数声明为一个指向常量的指针:
class String
{
public:
String (const char* = "");
};
上面的声明保证了String的构造函数不会通过它的指针参数进行存储修改。如果我们把String的构造函数声明为带有一个类型为char*而不是const char*的参数,那么所有有着常量指针的用户就无法用这个构造函数来构建一个String对象
class String
{
public:
String (char* = "");//应该为String (const char* = "");
};
int main()
{
const char* hello = "hello world";
String s(hello);//编译期错误,找不到合适的String构造函数
}
6.3常成员函数
通过在函数的声明体和定义体的参数列表后面添加关键字const,就可以把一个成员函数声明为一个常量成员函数。
class String
{
public:
int length() const;
void capitalize();
};
int String::length() const{}
void String::capitalize(){}
我们只能对常量对象调用常成员函数:
const String s("hello");
int len = s.length();//ok
s.capitalize();//编译期错误,对常量对象调用非常量成员函数
String t("world");
len = t.length();//ok
t.capitalize();//ok
在某些情况下,常成员函数会对数据成员进行修改,我们必须使用类型转换来去除该成员的常量性。