1. 程式人生 > >常型別(C++學習筆記 30)

常型別(C++學習筆記 30)

因為程式中各種形式的資料共享,在不同程度上破壞了資料的安全性。引入常型別的目的是,為了保證資料共享又防止資料被改動。

常型別是指使用型別修飾符 const 說明的型別,常型別的變數或物件成員的值在程式執行期間是不可改變的。
本文將從三方面入手:常引用、常物件和常物件成員。

一、常引用

  • 常引用: 在說明引用時用 const 修飾的引用。
  • 如果用 常引用作形參,便不會產生對實參的不希望的更改。
  • 常引用的說明形式:
    const 型別 &引用名;
    例如:
int a=5;
const int &b=a;

其中,b 是一個常引用,它所引用的物件不允許更改。如果出現:b=22;

則非法。

例 1:常引用作函式引數。

在實際應用中,常引用往往用來作函式的形參,這樣的引數稱為 常引數
用常引用作形參,能夠避免對實參的更改,保證資料的安全。

#include<iostream>
using namespace std;
int add(const int &i,const int &j);  //函式 add 的形參是常引用
int main(){
	int a=20;
	int b=30;
	cout<<a<<"+"<<b<<"="<<add(a,b)<<endl;
	a=
15; b=50; cout<<a<<"+"<<b<<"="<<add(a,b)<<endl; return 0; } int add(const int &i,const int &j){ //i=i+50; //不允許改變 i 的值,error是 assignment of read-only reference 'i' 即 給只讀引用值'i'賦值出現錯誤 return i+j; }

二、常物件

  • 常物件:在說明物件時用 const 修飾。
  • 常物件的資料成員值在物件的整個生存期內不能被改變。
  • 常物件的說明形式:
    類名 const 物件名[(引數表)];
    或者
    const 類名 物件名[(引數表)]
    在定義物件時必須進行初始化,而且不能被更新。

例 2:常物件 和 非 常物件 的比較

#include<iostream>
using namespace std;
class Sample{
	public:
		int m;
		Sample(int i,int j){
			m=i;
			n=j;
		}
		void setvalue(int i){
			n=i;
		}
		void display(){
			cout<<"m="<<m<<endl;
			cout<<"n="<<n<<endl;
		}
	private:
		int n;
};
int main(){
	Sample a(10,20);
	a.setvalue(40);
	a.m=30;
	a.display();
	return 0;
}

在例 2 中,物件 a 是一個普通的物件,而不是常物件,執行結果為:
在這裡插入圖片描述
若將上述的物件 a 定義為常物件,主函式修改一下:

int main(){
	const Sample a(10,20);  //a 是常物件,而不是普通物件 
	a.setvalue(40);	  //錯誤:不允許改變常物件的資料成員值 
	a.m=30;		//錯誤:不允許改變常物件的資料成員值 
	a.display();    //錯誤:不允許常物件呼叫普通的成員函式 
	return 0;
}

則會出現三處錯誤(要格外注意,第三處錯誤,不允許常物件呼叫普通的成員函式)。

三、常物件成員

1、常資料成員

  • 類的資料成員可以是常量或常引用,使用 const 說明的資料成員稱為 常資料成員
  • 如果在一個類中說明了常資料成員,那麼建構函式就只能通過成員初始化列表對該資料成員進行初始化,在建構函式的函式體內對常資料成員賦初值也是非法的,而且其他任何函式都不能對該成員賦值。
  • 一旦對某物件的常資料成員初始化後,該資料成員的值是不能改變的,但不同物件中的該資料成員的值可以是不同的(在定義物件時給出)。

例 4:常資料成員的使用。

#include<iostream>
using namespace std;
class Date{
	public:
		Date(int y,int m,int d);
		void showDate();
	private:
		const int year;  //常資料成員 
		const int month;
		const int day;
};
Date::Date(int y,int m,int d):year(y),month(m),day(d){
}
void Date::showDate(){
	cout<<year<<"."<<month<<"."<<day<<endl;
}
int main(){
	Date date1(2018,11,25);
	date1.showDate();
	return 0;
}

2、常成員函式

  • 在類中使用關鍵字 const 說明的成員函式為常成員函式。
  • 常成員函式的說明格式如下:
    型別說明符 函式名(引數表) const;
    const是函式型別的一個組成部分,因此在宣告和定義函式時都要有關鍵字 const,在呼叫時不必加 const。

例 5:常成員函式的使用(仔細看程式碼)。

#include<iostream>
using namespace std;
class Date{
	public:
		Date(int y,int m,int d);
		void showDate();  //宣告普通的成員函式 showDate 
		void showDate() const;  //宣告常成員函式 showDate 
	private:
		int year;  
		int month;
		int day;
};
Date::Date(int y,int m,int d):year(y),month(m),day(d){
}
void Date::showDate(){
	cout<<"showDate1:"<<endl;
	cout<<year<<"."<<month<<"."<<day<<endl;
}
void Date::showDate() const{
	cout<<"showDate2:"<<endl;
	cout<<year<<"."<<month<<"."<<day<<endl;
}
int main(){
	Date date1(2018,11,25);  //定義普通物件 date1 
	date1.showDate();
	const Date date2(2018,9,28);  //定義常物件 date2
	date2.showDate();
	return 0;
}

執行結果:
在這裡插入圖片描述
  在例 5中類 Date 說明了兩個同名的成員函式 showDate,一個是普通的成員函式,另一個是常成員函式,它們是過載的(關鍵字 const 可以被用於區分過載函式)。
  在主函式中說明了兩個物件 date1 和 date2,其中物件 date2 是常物件。通過物件 date1 呼叫的是沒有用 const 修飾的成員函式 showDate,而通過物件 date2 呼叫的是用 const 修飾的常成員函式 showDate。

說明注意:
(1)常成員函式可以訪問常資料成員,也可以訪問普通資料成員。


資料成員 普通成員函式 常成員函式
普通資料成員 可以訪問,也可以改變值 可以訪問,但不可以改變
常資料成員 可以訪問,但不可以改變值 可以訪問,但不可以改變
常物件的資料成員 不允許訪問和改變值 可以訪問,但不可以改變

(2)如果將一個物件說明為常物件,則通過該物件只能呼叫它的常成員函式,而不能呼叫普通的成員函式。所以說,常成員函式是常物件唯一的對外介面,這是C++從語法機制上對常物件的保護。
(3)常成員函式不能更新物件的資料成員,也不能呼叫該類中的普通成員函式,這就保證了在常成員函式中絕對不會更新資料成員的值。