c++常成員函式和常物件的注意事項
1.什麼是常成員函式
常成員函式,它就是在成員函式後面加一個const,用來修飾this指標所指的物件,使this指標所指的物件不受更改,保護它的資料安全。當常成員函式沒有引數的時候修飾的是this指標,有引數的時候就是修飾的引數和this!!反正就是不能變一切!!
除非本類中的變數是用mutable修飾,比如mutable int count;那麼則常成員函式中也是可以修改該變數的值的!
int getId() const
{
return this->id;
}
比如上面的成員函式就是一個常成員函式,const是修飾this指標所指的物件的,我們知道this指標其實就是一個指向物件的常指標
int getId(const Student * const this)
{
return this->id;
}
其實常成員函式的內部實現就是上面這樣的,只是我們不這樣書寫,後面的const修飾的是this指標(即這個this指標不能再加減,成為一個常量),前面的const修飾的是這個this常指標所指的物件(即這個物件不受改變)。
2.常物件和常成員函式應該注意的事情
我們先看一個demo
#define _CRT_SECURE_NO_WARNINGS #include<iostream> using namespace std; //建立一個Student類,包含id和name class Student { private: int id; char *name; public: Student(){ this->id = 0; this->name = NULL; } Student(int id, char *name) { this->id = 0; int len = strlen(name); this->name = new char[len + 1]; strcpy(this->name, name); } int getId() const { return this->id; } ~Student() { if (name != NULL) { delete name; name = NULL;//當游標在這個位置的時候按 Shift+},游標就會跳到下面的大括號外 } } }; //全域性函式display是為了接受一個Student物件的引用,然後為了保證display函式不會修改這個引用物件,就在前加了一個const修飾 //但是在用std.getId()輸出的時候爆出錯誤:物件含有與成員函式Student::getId不相容的型別限定符,物件型別是const Student //解決的辦法就是在物件的成員函式int getId(){}後面加一個const,修飾this指標所指的物件,讓這個所指的物件不發生改變。 void display(const Student & std) { cout << std.getId() << endl; } int main() { //建立一個Student物件 Student s1(1, "zhang3"); //呼叫全域性函式display display(s1); }
根據以上demo我們知道,如果在display()的形參中加了一個const修飾的話,那麼裡面呼叫的getId()函式也需要在Student類裡面宣告為const 常成員函式。當然如果形參中不加const修飾的話就不存在這個問題了。那這個問題怎麼來解釋了,可以從兩個角度來解釋,如下:
解釋一:我們看display函式中Const Student &std,表示這個傳進來的Student物件是不能修改的,但是在呼叫std.getId()的時候,getId()會把std物件通過this指標傳到這個函式裡面去(只是不需要把this顯示出來而已,但是實際上就這樣操作了),相當於這個getId()是下面這樣的:
int getId(Student * const this)
{
return this->id;
}
那麼也就是說,這個student物件從一個Const Student 賦值給了 Student ,這觸發了c++的安全檢測機制,就是“非常的”可以賦值給“常的”,但是“常的”不能賦值給“非常的”,因為這個破壞了“常的”安全,那豈不是就能改變了嗎,所以c++要求不能這樣做。
解釋二:也可以從另外一個角度來解釋,我們看display()的形參中,不是給Student &std加了一個const修飾嗎,就變成了
const Student & std,這是什麼?這是常物件,也就是將一個普通的物件接收後變成了一個常物件,常物件只能呼叫它的常成員函式而不能呼叫該物件的普通成員函式。所以,如果想要std.getId(),那麼這個函式getId()必須是常成員函式,還有一個需要注意的點,常成員函式不能改變資料成員,其實也不用死記,你都定義成常的了,你還去改變它幹嘛。