1. 程式人生 > >c++常成員函式和常物件的注意事項

c++常成員函式和常物件的注意事項

1.什麼是常成員函式

常成員函式,它就是在成員函式後面加一個const,用來修飾this指標所指的物件,使this指標所指的物件不受更改,保護它的資料安全。當常成員函式沒有引數的時候修飾的是this指標,有引數的時候就是修飾的引數和this!!反正就是不能變一切!!

除非本類中的變數是用mutable修飾,比如mutable int count;那麼則常成員函式中也是可以修改該變數的值的!

int getId() const
	{
		return this->id;
	}

比如上面的成員函式就是一個常成員函式,const是修飾this指標所指的物件的,我們知道this指標其實就是一個指向物件的常指標

,另外說一句c++中的引用也是傳遞的常指標,那麼這個常成員函式可以表示成這樣(假設它是我定義的Student類裡面的常成員函式):

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()必須是常成員函式,還有一個需要注意的點,常成員函式不能改變資料成員,其實也不用死記,你都定義成常的了,你還去改變它幹嘛。