C++ const成員函數小記

前言

今天在看《STL源碼解析》並仿寫queue時,遇到一個我經常會混淆的問題,如下:

template <class T, deque<T> >
class queue {
	……
public:
	// 非const成員函數,返回數據的引用
	reference front() { return c.front(); }
	// const成員函數,返回數據的常量引用
    const_reference front() const { return c.front(); }
	……
};

爲啥一個可以是非const的成員函數,而一個是const的成員函數。我想了一下,然後又想起了自己對const成員函數這一塊兒一直不是很熟,故重新看了看《C++ primer》,大概懂了一些。

const成員函數與非const成員函數

在《C++ primer》中作者提到,每次調用成員函數,都會隱式傳入一個指向對象的this指針。因爲它是成員函數的隱式參數,所以我們無法修改this指針,使其在作爲成員函數的參數傳入時成爲指向常量對象的指針。(當然this本身是一個常量指針,無法修改它保存的對象地址)那麼如果常量對象調用非const的成員函數,就肯定會無法調用。因爲this指針形參爲Data * const,也就是指向非常量對象的常量指針;而常量對象調用成員函數時,傳入的實參是const Data* const,形參與實參const類型不匹配,報錯!所以纔有了const成員函數。
const成員函數則修改了成員函數的隱式this指針形參,將其改成了const Data* const,也就是指向常量對象的常量指針,這就使得常量對象可以成功調用這個成員函數。書上舉了一個例子:

// 僞代碼,說明隱式的this指針是如何使用的
// 下面的代碼本身是非法的:因爲我們不能顯式地定義自己的this指針
// 謹記此處的this是一個指向常量的常量指針,因爲isbn是一個常量成員
string Data::isbn(const Data* const this) {
	return this->isbn;
}

在上例中因爲this指針是指向常量的指針,所以常量成員函數不能改變調用它的對象的內容。isbn可以讀取調用它的對象的數據成員,但是不能寫入新值。
正因爲const成員函數與非const成員函數在隱式this指針形參上const類型的不同,所以兩者通過參數const類型的不同實現函數的重載。非常量對象雖然可以調用非const成員函數和const成員函數,但是非const成員函數是最佳匹配;而常量對象只能調用const成員函數。這也是爲啥const成員函數能夠實現函數重載的原因。

總結

所以,const成員函數通過修改傳入成員函數的隱式this指針參數的const類型,限制傳入的this指針必須是指向常量對象的指針,從而實現在const成員函數中無法通過this指針來修改對象的內容(成員的值等)

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