const是一種約束,告訴編譯器和其他程序員,這個值不要被修改。
a.函數返回值是常量: 例如有理數的乘法重載:
const Rational operator* (const Rational& lhs, const Rational& rhs);
這樣寫可以避免一些暴行,例如 Rational a, b, c;
(a * b) = c;
b.const成員函數
將const實施於成員函數的目的,是爲了確認改成員函數可作用於const對象身上。
兩個成員函數如果只是常量性不同,可以被重載。例如:
using std::cout;
using std::endl;
using std::string;
class TextBlock
{
public:
const char& operator[](std::size_t position) const
{
cout << "const版本" << endl;
return text[position];
}
char& operator[](std::size_t position)
{
cout << "普通版本" << endl;
return text[position];
}
TextBlock(const string& s) :text{ s }
{
}
private:
std::string text;
};
void print(const TextBlock& tb)
{
cout << tb[0] << endl;
}
int main()
{
TextBlock tb{ "Hello" };
cout << tb[0] << endl; // 普通版本
const TextBlock ctb{"World"};
cout << ctb[0] << endl; // const普通版本
print(TextBlock{ "OhGod" }); // const普通版本
}
此小節也引出了mutable關鍵字。
c.在const和non-const成員函數中避免重複
上面的類中,constt版本和non-const版本在實際的代碼中可能會有大量相同的代碼,所以如果像重載一樣,能讓non-const版本調用const版本,
將會減少很多重複代碼:
char& operator[](std::size_t position)
{
return const_cast<char&>(static_cast<const TextBlock&>(*this)[position]);
//cout << "普通版本" << endl;
//return text[position];
}
先將*this轉換成const對象,然後就可以調用const版本的[],最後將返回值去const。
但是如果反過來,用const版本調用non-const是肯定不行的,因爲const承諾不改變對象的邏輯狀態。
總結
a.將某些東西聲明爲const可以幫助編譯器偵測出錯誤語法。const可被施加於任何作用於內的對象、函數參數、函數返回類型、成員函數本體。
b.編譯器強制實施bitwise constness,但你編寫程序時應該使用“概念上的常量性”(conceptual constness)。
c.當const和non-const成員函數有着實質等價的實現時,令non-const版本調用const版本可避免代碼重複。