【C++】const物件和const成員
如果我們在定義一個物件之後,不希望在後面對這個物件進行修改,那麼我們可以把這個物件宣告為const物件。
宣告為const物件之後,這個物件的所有資料成員後面都不能被修改!
const物件
定義類物件時可以將其指定為const物件。定義後const物件不能再被修改。
const物件不能呼叫非const型別的成員函式。
有兩種方法來定義一個const物件:
const 類名 物件名
類名 const 物件名
這兩種方法是等價的。
如果一個物件被定義成const物件,那麼它就不能呼叫這個類中的非const成員函式。
const物件呼叫的成員函式一定都得是const!
//const
const CTime time4(10);
CTime const time5;
如果你用const物件引用了這個類中的非const成員函式,就會報錯:
錯誤 1 error C2662: “int CTime::getHour(void)”: 不能將“this”指標從“const CTime”轉換為“CTime &”
e:\chenhaoxiang\20170603\test2\test2\mian.cpp 34 1 test2
其實就是告訴我們const物件不能引用非const成員函式
為什麼要有這個規則:
因為在非const成員函式內部可能對物件進行修改,比如set函式
這個規則也就是強制使用者不要對const成員進行錯誤的修改
const成員
1.const資料成員
也就是變數,比如例項中的m_hour,m_minute是普通資料成員
在類內部使用const關鍵字來宣告const資料成員。const資料成員的值不能被修改。
初始化時比較特殊,只能通過初始化列表初始化。不能在建構函式裡賦值。
2.初始化列表
初始化列表:
除了在建構函式中對資料成員進行初始化,C++還提供另外一種方法來對資料成員進行初始化
初始化列表並不是在建構函式內進行初始化
建構函式初始化列表以一個冒號開始,接著是以逗號分隔的資料成員列表,每個資料成員後面跟一個放在括號中的初始化式。
const int num;
必須初始化,而且不能在建構函式中初始化!
CTime::CTime() : num(10){
m_hour = 0;
m_minute = 0;
m_second = 0;
m_nNum++;
cout << m_nNum << endl;
}
CTime::CTime(int hour) : num(10){
this->m_hour = hour;
//(*this).m_hour = hour; //效果一樣的
}
//複製建構函式
CTime::CTime(CTime& time) : num(10){
m_hour = time.m_hour;
m_minute = time.m_minute;
m_second = time.m_second;
//cout << "進入複製建構函式" << endl;
}
每一個建構函式都需要初始化這個const成員,而且複製建構函式也需要初始化num,因為複製建構函式也是一種建構函式!
3.const成員函式
const成員函式只能被const物件引用。const成員函式內可以引用const資料成員,也可以引用非const資料成員,但不能修改非const資料成員的值。但不能呼叫非const成員函式。
int getNum() const;
對於const函式的外部定義,也需要寫const限定符
int CTime::getNum() const {
return num;
}
const成員函式存在的意義在於它能被const常物件呼叫
CTime const time5;
cout << time5.getNum() <<endl;
如果在const成員函式的定義中出現了任何修改物件成員資料的現象,都會在編譯時被檢查出來
如果我們是真的想在const成員函式中修改值呢,比如我需要m_age++;
比如下面定義了一個m_age 類成員:
int m_age;
int CTime::getNum() const {
if (m_age == 0){
m_age++;
}
else{
m_age = 0;
}
return num;
}
假如我們不做其他事情,這樣的寫法,在編譯時是無法通過的。
有些時候,我們想要讓const函式具有修改某個成員資料值的能力。
比如一些內部的狀態量,對外部使用者無所謂,但是對整個物件的執行卻大有用處,如支援快取的技術。
遇到這種問題,我們可以把一個成員資料定義為mutable(多變的),它表示這個成員變數可以被const成員函式修改卻不違法。
比如下面定義了這樣一個m_age 類成員:
mutable int m_age;
int CTime::getNum() const {
if (m_age == 0){
m_age++;
}
else{
m_age = 0;
}
return num;
}
這樣,即使像getNum()這樣的const成員函式修改它也是合法的。
但需要注意的時,不要濫用mutabe描述符,如果在某個類中只有少數一部分是被允許const常量函式修改的,使用mutable是再合適不過的。如果大部分資料都定義為mutable,那麼最好將這些需要修改的資料放入另一個獨立的物件裡,並間接地訪問它。
原始碼下載地址:
GITHUB原始碼下載地址:
本文章由[諳憶]編寫, 所有權利保留。
歡迎轉載,分享是進步的源泉。
相關推薦
【C#】面對物件和類、構造方法及名稱空間
一、面向物件 1、什麼是面向物件? 面向物件是一種思想,面向物件是將功能等通過物件來實現,將功能封裝進物件之中,讓物件去實現具體的細節,在面向物件中,將資料作為第一位,而方法或者說是演算法作為其次,這是對資料的一種優化,操作起來更加方便,簡化了過程。 2、為什麼要用面向
【C++】const物件和const成員
如果我們在定義一個物件之後,不希望在後面對這個物件進行修改,那麼我們可以把這個物件宣告為const物件。 宣告為const物件之後,這個物件的所有資料成員後面都不能被修改! const物件 定義類物件時可以將其指定為const物件。定義後c
【C++】初學類和物件的概念
C++中的類Class可以看作C語言中結構體的升級版。結構體是一種構造型別,它可以包含若干成員變數,而其中每個成員變數的型別又可以不同。例如: struct Student {//結構體包含的成員變數 char *name; int age; float score; }; void D
【C++】boost::bind和函式物件一起使用實現便捷的非同步程式設計
在C++面向物件程式設計中,觀察者模式是大家熟知的實現非同步程式設計的一種模式。 觀察者模式定義物件間的一種一對多的依賴關係,以便當一個物件的狀態發生改變時,所有依賴於它的物件都得到通知並自動更新。如下圖所示: 觀察者模式提供了一種物件設計,
C++ 中臨時物件 和 const 物件 的一個區別
C++ 中臨時物件和const物件的一個區別 const 物件特點 1,只能作為右值 2,只能呼叫物件的const方法 臨時物件特點 1,只有作為為 const& 賦值
【C++】隨機數rand( ) 和 隨機數引擎
rand() 基本:使用隨機數時,經常見到的是C標準庫提供的函式rand(),這個函式會生成一個0到RAND_MAX(32767)之間的一個整形數; 分佈:為了得到一個給定範圍內的隨機數,通常會對生成的隨機數取餘:rand()%n,rand()%(n-m)+m; 種子:通過
【C++】建立物件之new關鍵字
起初剛學C++時,很不習慣用new,後來看老外的程式,發現幾乎都是使用new,想一想區別也不是太大,但是在大一點的專案設計中,有時候不使用new的確會帶來很多問題。當然這都是跟new的用法有關的。new建立類物件,使用完後需使用delete刪除,跟申請記憶體類似。所以,new有時候又不太適合,比如在
【C#】靜態變數和方法該如何使用?
什麼是靜態變數? 簡單的來說就是:用static修飾的變數,它屬於它所在的類所有,而不是具體的某一個物件。 靜態變數也被稱為全域性變數,就是它在程式執行的時候就被初始化,如果你在它初始化或使用的時候,沒有給它賦值,系統就會給它一個預設值。 靜態方法同理,簡單瞭解一下
【JavaScript】Bom物件和Dom物件
BOM:Browser Object Model(瀏覽器物件模型) 就是在JS程式碼中可以直接使用的物件,但是物件都是和瀏覽器有關的 Example: <script> window.close(); </script> (1)Wi
【C#】Parallel.For 和 For 誰的效率高呢?
原標題:C# 多執行緒 Parallel.For 和 For 誰的效率高?那麼 Parallel.ForEach 和 ForEach 呢? 今天和大家探討一個問題:Parallel.For 和 For 誰的效率高呢? 從CPU使用方面而言,Parallel.For
【C++】友元與靜態成員
友元 C++中,類外的成員不能訪問類內的私有和保護型別成員。而友元函式可以不受訪問限制訪問類的任何成員。友元函式雖然可以在類內進行宣告,但是友元函式不是成員函式,因此沒有this指標。 舉例說明: class Clock { public: Clo
【C++】堆記憶體和棧記憶體詳解
一個由C/C++編譯的程式佔用的記憶體分為以下幾個部分 1、棧區(stack)— 由編譯器自動分配釋放 ,存放函式的引數值,區域性變數的值等。其操作方式類似於資料結構中的棧 2、堆區(heap) — 一般由程式設計師分配釋放, 若程式設計師不釋放,程式結束時可能由OS回
【C++】靜態分配和動態分配 堆和棧(詳解)
但是,在使用陣列的時候,總有一個問題困擾著我們:陣列應該有多大?在很多的情況下,你並不能確定要使用多大的陣列,比如上例,你可能並不知道我們要定義的這個陣列到底有多大,那麼你就要把陣列定義得足夠大。這樣,你的程式在執行時就申請了固定大小的你認為足夠大的記憶體空間。即使你知道你想利用的空間大小,但是如果因為某種特
【C++】STL佇列和棧的使用
C++的STL標準模板庫提供了佇列和棧的基本操作。下面通過兩個demo分別介紹STL佇列和STL棧的使用。 Demo1:STL佇列 【題目】卡片遊戲(題目來自劉汝佳《演算法競賽入門》) 桌上又一疊牌,
【C++】vector容器和list容器中使用單個迭代器的erase函式學習筆記
例題為:假設有如下ia的定義,ia複製到vector和list中,把list容器中奇數值元素刪除掉,把vector容器偶數值元素刪除掉。 陣列複製採用push_back操作。刪除操作採用了erase函式,由於該函式返回值為指向被刪除元素後面的元素,則使用了返回值賦值回給迭代
【C#】Linq表示式和Lambda表示式用法對比
什麼是Linq表示式?什麼是Lambda表示式? 前一段時間用到這個只是,在網上也沒找到比較簡單明瞭的方法,今天就整理了一下相關知識,有空了再仔細研究研究 using System; using System.Collections.Generic; using S
【C++】目標檔案和可執行檔案裡面都有什麼
編譯器編譯原始碼後生成的檔案叫做目標檔案。 從檔案結構上來講,目標檔案已經是二進位制檔案。 編譯是針對單個原始檔的,有幾個原始檔就會生成幾個目標檔案,並且在生成過程中不受其他原始檔的影響。也就是說,不管當前工程中有多少個原始檔,編譯器每次只編譯一個原始檔、生成一個
【C#】 陣列排序和取值練習
1.從鍵盤接收一行用逗號分隔的5個整數,儲存至有5個元素的陣列中。 2.分別輸出正序和逆序的結果。 3/輸出陣列最大值和平均值,平均值保留1位小數。 4.存在非法輸入時顯示提示訊息並可重新輸入資料。 5.按下回車鍵退出,任意鍵繼續輸入。 輸出結果如圖所示。 -------
【C++】const char* 和char* 之間的轉換
const char*是指向常量的指標,而不是指標本身為常量,可以不被初始化.該指標可以指向常量也可以指向變數,只是從該指標的角度而言,它所指向的是常量, 通過該指標不能修改它所指向的資料. 1.const char*是不能直接賦值到char*的,這樣編譯都不能通過,理由
【C++】類中成員函式聲明後面接 const
const 表示對類中成員函式屬性的宣告; 表示不會修改類中的資料成員; 在編寫const成員函式時,若不慎修改了資料成員,或者呼叫了其他非const成員函式,編譯器將指出錯誤; 以下程式中,類stack的成員函式GetCount僅用於計數,從邏輯上講GetCount應