C++之const關鍵字的幾種用法

@著作權歸作者所有:來自CSDN博客作者大鬍子的艾娃的原創作品,如需轉載,請註明出處https://blog.csdn.net/qq_43148810,否則將追究法律責任。
如有錯誤的地方歡迎指正,謝謝!

一、常變量

const 數據類型 變量名 = 值;
例如:
const int i = 1;
i = 2;//錯誤
//const int j ;j = 1;錯誤

聲明的同時必須初始化,雖爲變量,但是不能更新其值。
又有常量性質,可以進行數組大小的確定,int a[i] = { 2 }; ,是因爲const編譯時,執行。
儲存數據區域和定義位置(全局,函數內,類中等)有關。

二、常引用

const 數據類型 & 引用變量名 = 變量名;
例如:
int i = 1;
const int j = 2;
const int & m = i; //常量引用,引用非常量。
{
m = 3;//錯誤,m爲常變量,不能更新。
i = 3;正確,並且i和m的值都更新爲3了,即可以利用被引用的變量值的更新來釜底抽薪修改常引用的變量的值。
}
const int & m = j; //常量引用,引用常變量,並且m和j的值都不可更新。
int & m = j; //錯誤,j 爲常變量,m 爲非常量引用,引用是已存在變量的別名,此時m和j不能等價。

const int & 爲“常量引用”,對象可以是常量,也可以是非常量。
注意:常引用可以引用非常量、常變量。而非常量引用只能引用非常量。

三、指針常量(指向變量的常指針)

數據類型 * const 指針變量名 = 變量名;
例如:
int i = 1;
int j = 2;
int * const m = &i;
// int * const m;m = &i;錯誤,常指針,指針必須初始化。
m = &j;m = NULL;//都錯誤,指針常量指向不可被修改。

注意:指針常量(數據類型 * const)的“常”修飾的時指針,不是指向的值,所以指針爲“常”,指向的值可更新(*m=2;*m=j)。

四、常量指針(常變量的指針)

const數據類型 * 指針變量名 = 變量名;
例如:
const int i = 1;
int j = 2;
const int * m = &i;
m = &j;m = NULL;//都正確,常量指針指向可被修改。

const int a[3]={1,2,3};//常數組每個元素必須初始化,並不可修改其值。
數組名作爲指針時不能賦值給非常量指針。

注意1:常量指針(const數據類型 *)的“常”修飾的時變量,不是指針,即指針指向常變量,指向的值不可更新(*m=2;m=j)。
注意2:常量指針不可以賦值給非常量指針(int * p = m;錯誤),但是非常量指針可以賦值給常量指針(int * q =&j;m = j;正確)。
注意3:vs2017中“ char
str = “1234asd56”; ” 會報錯:"const char * "類型的值不能用於初始化"char * "類型的實體,但是VS2015及其以前的版本都不會報錯警告之類的。

五、指向常量的常量指針

const數據類型 * const 指針變量名 = 變量名;
例如:
const int i = 1;
int j = 2;
const int * const m = &i;

注意:指針和指向的值都被“常”所修飾,所以都不可修改。

六、const修飾函數形參

參考以上內容

例如1:
int sun ( const int a, const int b )
{
//a = 1;錯誤。
return a + b;
}
函數參數表中,含有兩個const 形參:a,b。const的存在使得sum函數只能使用a,b的值而不能修改。

例如2:
int sun ( const int & a, const int & b )
{
//a = 1;錯誤。
return a + b;
}
函數參數表中,含有兩個形參a和b對實參的引用,引用是對指針的封裝,實參會隨形參值變化而變化。const的存在使得sum函數只能使用a,b的值而不能修改,所以實參的值也不會因調用此函數而修改。

例如3:
char *strcpy(char * str1,const char * str2)
函數參數表中,由於str1是需要修改的,所以不用const修飾,而str2是傳遞數據進來的,並不希望進行改變,所以可以用const修飾。

七、const修飾函數返回值

修飾函數的返回值,意味着該返回值不能被修改。如果傳值並返回地址,const將保證該地址上的內容不會被改變。這就意味着該函數不能作爲左值使用,在這種情況下,const通常也是與引用和指針一起使用的。

八、類中的const(修飾成員數據,成員函數和類的對象)

1、修飾成員數據
有普通常變量,指針常量和常量指針,普通常變量數據成員和指針常量數據成員在C++中要在類的初始化列表中初始化,但是靜態常數據成員在類外說明和初始化。

#include<iostream>
using namespace std;
class A {
private:
	const int& r;         //常引用數據成員
	const int a;          //常數據成員
	static const  int b;   //靜態常數據成員
public:
	A(int i) :a(i), r(a)   //常數據成員只能通過初始化列表來獲得初值
	{
		cout << "constructor!" << endl;
	};
	void display()
	{
		cout << a << "," << b << "," << r << endl;
	}
};
const int A::b = 3;         //靜態常數據成員在類外說明和初始化
int main()
{
	A a1(1);
	a1.display();
	A a2(2);
	a2.display();
	return 0;
}

2、修飾成員函數
該成員函數不更新對象的數據成員,一般都加上const修飾,也建議這麼做。

在定義與使用常成員函數時要注意:
a、const是函數類型的一個組成部分,因此在函數實現部分也要帶有const關鍵字。
b、常成員函數不能更新對象的數據成員,也不能調用該類中沒有用const修飾的成員函數。
c、常對象只能調用它的常成員函數,而不能調用其他成員函數。這是C++語法機制上對常對象的保護,也是常對象唯一的對外接口方式。
d、const關鍵字可以用於參與重載函數的區分。一般對象可以調用常成員函數也可以調用一般成員函數,重載時優先選擇調用一般成員函數。

注意:這裏建議不更新對象的數據成員都寫成常成員函數,是爲了可供常對象調用,但是該常成員函數又不能調用該類中沒有用const修飾(修改了對象的數據成員)的成員函數。可能會存在矛盾,所以說一般、建議,但不得不說是個良好的習慣。

3、修飾類的對象
表示該對象爲常量對象,在對象的生命期中其中的任何成員都不能被修改,必須在定義的時候由構造函數初始化。常對象不能訪問非常成員函數,只能訪問常成員函數。

   #include <iostream>
using namespace std;
class Clock {
private:
	int H, M, S;
public:
	Clock(int H = 0, int M = 0, int S = 0)//構造函數
	{
		this->H = H, this->M = M, this->S = S;
	}
	Clock(Clock&p)//拷貝構造函數
	{
		this->H = p.H, this->M = p.M, this->S = p.S + 1;//S+1標記和構造區分,從而知道調用的時哪個函數
	}
	void ShowTime()
	{
		cout << H << ":" << M << ":" << S << endl;
	}
	void ShowTime ()const         //常成員函數
	{
		cout << "const: " ;
		cout << H << ":" << M << ":" << S << endl;
	}
	void SetTime(int H = 0, int M = 0, int S = 0)
	{
		this->H = H, this->M = M, this->S = S;
	}
	
};
int main()
{
	Clock C1(10, 10, 10);              //定義對象C1,並初始化,調用構造函數
	Clock const C2(9, 9, 9);           //定義常對象C2,並初始化,調用構造函數
	Clock const C3(C1);                //定義常對象C3,並初始化,調用拷貝構造函數
	Clock const C4;                    //定義常對象C4,並初始化,調用構造函數
	C1.ShowTime();            
	C2.ShowTime();
	C3.ShowTime();
	C4.ShowTime();
	C1.SetTime(0, 0, 0);
	C1.ShowTime();
	//C2.SetTime(0,0,0);        //錯誤!C1爲常對象,不能調用非常成員函數,也不能被更新!
	return 0;
}
/*
運行結果
10:10:10
const: 9:9:9
const: 10:10:11
const: 0:0:0
0:0:0
*/

a、33-35行是常對象的三種定義並初始化情況,注意Clock const C4; 時,構造函數形參必須默認初始值。

b、36行和41行說明了一般對象調用成員函數重載時優先選擇調用一般成員函數,並不會產生二義性。也就是說,如果只有常成員函數,一般對象會調用常成員函數。

c、常對象,不能調用非常成員函數,也不能被更新!

更多內容請關注個人博客:https://blog.csdn.net/qq_43148810

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