你所不知道的 const

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;

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章