const 修飾成員函數表示這個成員函數不能修改類的成員變量,因此這種成員函數稱為常量成員函數。這樣,編譯器可以對這個函數進行深度的優化。另外,一個類的常量型示例只能調用常量型成員函數。比如下面這個例子。
class Test
{
public:
Test();
int getValue() const;
int value();
private:
int intValue;
};
Test::Test():
intValue(1)
{
}
int Test::getValue() const
{
return intValue;
}
int Test::value()
{
return intValue;
}
類 Test 有 getValue() 和 value() 兩個成員函數,其中一個是常量型的。那麼下面的代碼中:
int main()
{
Test A;
const Test B;
cout << A.getValue() << endl;
cout << A.value() << endl;
cout << A.getValue() << endl;
cout << B.value() << endl;
return 0;
}
B.value() 的訪問就是非法的,因為 B 是常量,只能訪問常量型成員函數。
作為一種良好的習慣,我們應該將類中所有不修改成員變量的函數都設為 const 型。
不過 const 型成員函數並非絕對不會改變類的成員。比如下面的代碼:
#include
using namespace std;
char STRING[] = "A STRING!";
class Test
{
public:
Test();
char * changeStr() const;
private:
char *str;
};
Test::Test():
str(STRING)
{
}
char * Test::changeStr() const
{
str[1] = 'x';
return str;
}
int main()
{
const Test A;
cout << A.changeStr();
return 0;
}
const 修飾符只能保證指針 str 指向的地址不被修改。而指向的字符串的值是可以隨便改的。 如果將 str 從 char * 類型改為數組就不一樣了。下面的代碼無法編譯。因為 str[1] = ‘x’ 這個操作是非法的。
#include
using namespace std;
class Test
{
public:
Test();
char * changeStr() const ;
private:
char str[10];
};
Test::Test()
{
strcpy(str, "A STRING!");
}
char * Test::changeStr() const
{
str[1] = 'x';
return str;
}
int main()
{
Test A;
cout << A.changeStr();
return 0;
}
與 const 相反,volatile 表示這個函數裡訪問的變量可能由於其他原因發生改變。比如其他線程可能會對這些變量賦值,或者硬件會有寫其他的機制改變這些變量的值。這時這樣的函數就應該用 volatile 關鍵字修飾,相當於告訴編譯器,這個函數裡訪問的變量的值隨時都可能變化,所以不要做訪問優化。下面是個例子,A 被定義為 volatile 型變量,A.value() 必須要定義為 volatile,否則不能訪問。
#include
using namespace std;
class Test
{
public:
Test();
int value() volatile;
private:
int v;
};
Test::Test()
{
v = 1;
}
int Test::value() volatile
{
return v;
}
int main()
{
volatile Test A;
cout << A.value() << endl;
return 0;
}
volatile 和 const 也可以同時修飾一個函數。表示這個函數本身不修改變量的值,但是變量的值可能會自己變化。下面是例子:
#include
using namespace std;
class Test
{
public:
Test();
int value() volatile const;
private:
int v;
};
Test::Test()
{
v = 1;
}
int Test::value() volatile const
{
return v;
}
int main()
{
volatile const Test A;
cout << A.value() << endl;
return 0;
}