1. const对象的初始化
const 常量是不可修改的,也就是说only read,例如
const int nBuffSize = 512;
nBuffSize = 0; //error
就是因为const 常量不能修改,所以定义时必须初始化
2. const对象的文件局部性
默认在全局作用域中定义的非const变量可以在整个程序中访问,例如
//file1.c
int nCounter;
//file2.c
extern int nCounter;
++nCounter;
但是在全局作用域中声明的const变量是定义的文件局部变量,只能被该文件使用,不能被其他文件使用。可以通过指定const变量为extern,就可以在全局中使用,如下
//file1.c
extern const int nCounter = 1024;
//file2.c
extern int nCounter;
非const变量默认为extern,要使const变量能够在其他文件中访问,必须显示地指定它为extern
3. 指向const对象的指针和const指针
先看下面的例子
const int *p;
int * const p;
第一个就是指向的内容为const,而第二个是指针为const
另外要注意:不能使用void*指针保存const对象的地址,必须使用const void*,如下
const int nBuff = 42;
const void* pv1 = & nBuff;
void * pv2 = &nBuff; //error
4.const隐式转换
当使用非const对象初始化const对象的引用时,可以将非const对象转换为const对象,如下
int nVala = 10;
const int nValb = 0;
const int &nValc = nVala;
const int *pVald = &nValb;
当要使用非const变量初始化const变量,必须要将非const变量初始化,如下
int iVal = 123;
const int m = iVal;
5. 强制类型转换const_cast
const_cast就是隐式转换掉表达式的const性质,假设有函数string_copy,我们对其char*参数只读不写
const char* pc_str = "hello world!";
char* pc = string_copy(const_cast<char*>(pc_str));
6. const形参的复制
1)在调用函数的时候,如果函数使用非引用的非const形参,则可以传递const实参也可以额传递非const实参,如下:
int func(int, int);
const int nVal1 = 3, nVal2 = 6;
int nVal3 = 12, nVal4 = 13;
int nResult1 = func(nVal1, nVal2);
int nResult2 = func(nVal3, nVal4);
传递的实参类型为const int的调用,因为初始化复制了形参的值,可用const对象初始化非const对象,反之亦然。
2)如果将形参定义为非引用的const类型,不可以改变实参的局部副本,由于实参仍是以副本的形式传递,因此传递给函数的既可以是const对象也可以是非const对象。利用const引用形参可以避免复制实参,因为对于大部分的类类型或者大型数组,复制的效率太低下了,使用引用形参可以直接访问实参对象,而无需复制它,如下
int GetSqListElem(const SqList &L, const ElemType data); //得到线性表中数据为data的第一个索引位置
第个形参可以避免复制结构体L,使用const引用可以避免复制,同时避免修改实参参值,第二个虽然使用了const 但是没有使用引用,所以还是会复制实参
7. const成员函数返回*this
在普通的非const成员函数中,this的类型是一个指向类类型的const指针,为什么指针是const?因为当前对象已经确定,改变指针的值就是改变指向的对象。在const成员函数中,this指针是一个指向const类类型的const指针,也就是说指针不能改变,同时指向的内容也不能改变,也就是说不能改变对象的成员和函数,只能获取成员的值或者函数等,如下:
/*注意const成员函数的*this返回值为const screen*/
const screen& screen::display(ostream& os) const
{
cout << "const:";
do_display(os);
return *this;
}
注意这里返回的是*this,就是const screen
8. 基于const的重载
const对象只能使用const成员,非const对象可以使用任一成员。如下:
public:
//重载函数
screen& display(ostream& os); // 可以使用任何成员
const screen& display(ostream& os) const; //只能使用const成员
private:
void do_display(ostream& os) const;
如下调用
string str = "abcdefg";
screen myscreen(str, 0, 5); //栈上分配的空间
const screen constscreen(str, 0, 4);
myscreen.display(cout);
constscreen.display(cout);
这里调试一下,就会发现const版本的就只会调用const函数
9. 用于类对象的const构造函数
构造函数不能声明为const,因为构造函数就是要初始化类,如果声明为const就无法初始化
public:
sales_item(void) const;
这样编译的话就会出错
10. const static成员
一般,类的static成员,是不能在类的定义体中初始化,相反static数据成员通常在定义时初始化,整型const static数据成员就可以在类的定义体中进行初始化:
typedef double Money;
class account
{
public:
account(){};
~account(){};
Money balance(){ return bal; }
static double rate(){ return interestRate; }
static void rate(double);
private:
typedef long double Money;
Money bal;
static double interestRate;
static const int period = 30;
double daily_tbl[period];
};
const static数据成员在类的定义体中初始化时,该数据成员仍必须在类的定义体外进行定义,在类内部指定初始化值,成员的定义不必再指定初始值,如下
const int account::period;