c++中關於const的用法有很多,const既可以修飾變量,也可以函數,不同的環境下,是有不同的含義。今天來講講const加在函數前和函數后面的區別。比如:
01 |
#include<iostream> |
02 |
03 |
using namespace std; |
04 |
05 |
// Ahthor: 過往記憶 |
06 |
// E-mail: wyphao.2007@163.com |
07 |
// Blog: http://www.iteblog.com |
08 |
// 轉載請注明出處 |
09 |
10 |
class TestClass { |
11 |
public: |
12 |
size_t length() const; |
13 |
const char* getPContent(); |
14 |
void setLengthValid(bool isLengthValid); |
15 |
private: |
16 |
char *pContent; |
17 |
size_t contentLength; //A |
18 |
bool lengthIsValid; //B |
19 |
size_t precontentLength; |
20 |
}; |
21 |
22 |
size_t TestClass::length() const{ //函數名后加const |
23 |
if(!lengthIsValid){ |
24 |
contentLength= strlen(pContent); //C |
25 |
lengthIsValid = true; //D |
26 |
} |
27 |
28 |
return contentLength; |
29 |
} |
30 |
31 |
const char* TestClass::getPContent(){//函數名前加const |
32 |
return pContent; |
33 |
} |
34 |
35 |
void TestClass::setLengthValid(bool isLengthValid){ |
36 |
lengthIsValid = isLengthValid; |
37 |
} |
38 |
39 |
int main(void){ |
40 |
TestClass *tc =new TestClass; |
41 |
tc->setLengthValid(false); |
42 |
tc->length(); |
43 |
char * content = tc->getPContent(); //E |
44 |
return 0; |
45 |
} |
其中類TestClass中的length函數和getPContent函數分別在函數名后和前加了const修飾符,如果試圖編譯上面的代碼,將會得到下面的錯誤:
1 |
--------------------配置: mingw5 - CUI Debug, 編譯器類型: MinGW-------------------- |
2 |
檢查文件依賴性... |
3 |
正在編譯 C:\Users\wyp\Desktop\未命名1.cpp... |
4 |
[Error] C:\Users\wyp\Desktop\未命名1.cpp:24: error: assignment of data-member `TestClass::contentLength' in read-only structure |
5 |
[Error] C:\Users\wyp\Desktop\未命名1.cpp:25: error: assignment of data-member `TestClass::lengthIsValid' in read-only structure |
6 |
[Error] C:\Users\wyp\Desktop\未命名1.cpp:43: error: invalid conversion from `const char*' to `char*' |
7 |
[Warning] C:\Users\wyp\Desktop\未命名1.cpp:45:2: warning: no newline at end of file |
8 |
9 |
構建中止 未命名1: 3 個錯誤, 1 個警告 |
里面有三個錯誤,也就是代碼C、D、E處的三個地方。為什么C和D處的代碼會出錯,原因如下:
length函數名的后面加了const修飾符,這樣說明函數的成員對象是不允許修改的。我們都知道,在類的成員函數里面,默認是在成員函數的第一個位置 是this指針,如果在成員函數(只能是成員函數,要是類的靜態函數或者是非成員函數就不可以在函數名后面加上const)后面const,則說明 this指針的值是不可以修改的,只能讀取。而上面的length函數可能會修改里面的contentLength和lengthIsValid的值,這 樣編譯器肯定是不允許的,所以這樣是會出現錯誤的。
解決方法是:在類的A、B處的成員前面加上mutable修飾符:
1 |
mutable size_t contentLength; //A |
2 |
mutable bool lengthIsValid; //B |
從字面的意思知道,mutalbe是“可變的,易變的”,跟constant(既C++中的const)是反義詞。在C++中,mutable也是 為了突破const的限制而設置的。被mutable修飾的變量,將永遠處於可變的狀態,即使在一個const函數中。這樣在C、D處將不會出錯。
那么,為什么E處出現了錯誤。這是因為在函數名getPContent前加了const修飾符,意味着該函數返回的值只能是讀取,而不能被修改。而E處的content卻為char *是可以被修改的,這與const正好相反了,所以出現了錯誤。解決方法是:在char *前面加上const修飾符,即:
1 |
const char * content = tc->getPContent(); //E |
再去編譯運行,這樣就不會出現錯誤了。
