const限定
(1)限定一個對象
C語言使用預處理指令#define定義符號常量,但是這種常量的缺點在於它只是進行簡單的字符串替換,
不進行類型檢查。const限定將一個對象限定爲常量。例如:
const int bufSize = 1024;
定義bufSize爲一個常量,初始化爲1024,企圖修改這個值會導致編譯錯誤。因爲常量的值不能修改,
所以必須在定義時初始化。
(2)限定指針
限定指針有兩種,例如:
int ival = 1024;
const int* pi = & ival; //第一種
int* const pi2 = & ival; //第二種
(注意:const指針必須初始化)
第一種const是限定int,表示指針pi指向內存單元的值(*pi)是常量,不能改變。
第二種const是限定int*,表示指針pi的值是一個常量,不能改變。
所以有:
*pi = 1000; //error,pi指向內存單元的值不能改變。
int ival2 = 1000;
pi2 = &ival2; //error,指針pi一旦指定就不能改變。
#1.const地址不能賦值給非const指針
#2.非const地址和const地址都能賦值給const指針
int ival = 1024;
const int ival2 = 1000;
const int* pi = &ival; //ok,將int*類型的地址賦值給const int*類型指針
pi = &ival2; //ok,將const int*類型的地址賦值給const int*類型指針
*pi = 2000; //error, 指針指向內存單元的值不能修改
int* const pi2 = &ival; //ok,將int*類型的地址賦值給int* const類型的指針
*pi2 = 1000; //ok, 對於*pi沒有限定,且內存單元值沒有const限定,可以修改
pi2 = &ival2; //error,const限定int*,指針pi2的值不能改變
(3).const限定函數參數和函數返回值
對按值傳遞的函數參數和函數返回值, const限定沒有任何意義,
而對於引用和指針傳遞的函數參數或函數返回值,可以使用const限定。
例如:
const string& longerString(const string &sa, const string &sb)
{
return sa.size() > sb.size() ? sa : sb;
}
(4)const數據成員
const可以限定類中的數據成員,const數據成員一般用來描述對象中的常量。
在數據成員前添加const關鍵字就將其限定爲常量。const數據成員在構造函數
的初始化列表中初始化。創建對象時初始化其中的const數據成員,之後的const
成員的值在對象的整個生成期中都不會改變。
例如:
class ClassA
{
private:
const int m_Num; //僅僅一個數值
public:
ClassA(int num) :m_Num(num){}
virtual ~ClassA(){}
};
ClassA a(10); ClassA b(20); //每個ClassA的對象都有保存一個const數值,在初始化後都不會改變
(5)const成員函數
和普通的內置數據類型對象一樣,一個類的對象也可以限定爲const;
如:
const int ival = 1024;
const ClassA a(10); //對象a爲常量對象,修改該類對象會引起編譯錯誤
將一個成員函數聲明爲const,表明這個成員函數不會修改對象的數據成員,能保證對象的常量性。
聲明const成員函數的語法形式爲:
返回類型 成員函數名 (參數表) const;
定義const成員函數的語法形式爲:
返回類型 成員函數名 (參數表) const {函數體}
例如:
//ClassA.h
class ClassA
{
private:
int m_Num; //僅僅一個數值
public:
ClassA(int num) :m_Num(num){}
virtual ~ClassA(){}
void setNum(int num){ m_Num = num; } //設置m_Num的值
int getNum() const { return m_Num; } //得到m_Num的值
};
//main.cpp
#include<iostream>
using namespace std;
#include "ClassA.h"
int main(char argc, char* argv[])
{
const ClassA a(5); //const對象
a.getNum(); //OK
a.setNum(20); //error
return 0;
}
只有聲明爲const的成員函數才能被const對象調用。const對象不能調用非const成員函數,但是非const對象可以調用const成員函數。
const成員函數中不能修改類的數據成員,也不能調用其他非const成員函數,否則會引起編譯錯誤。
const在限定成員函數時對其參數表產生了影響。ClassA類的成員函數的第一個隱含參數是ClassA*類型的this指針。但是const
ClassA對象的地址是const ClassA*類型的,用const ClassA對象調用非const 成員函數時,編譯器報告的錯誤是:“參數類型不匹配:不能
將實參從const ClassA*轉換爲ClassA*"。這實際上反映的是隱含this指針類型錯誤。
const限定的成員函數其實是將const關鍵字作用於隱含的this指針,其類型成爲了const ClassA*。因此編譯器防止以任何方式
通過this指針來修改當前對象的狀態,從而保證了對象其生成期間的常量性。