目錄
1.1 const obj 如果調用 non-const member fun會編譯出錯
1.const
class complex
{
public:
complex (double r = 0, double i = 0): re (r), im (i) { }
complex& operator += (const complex&);
complex& operator -= (const complex&);
complex& operator *= (const complex&);
complex& operator /= (const complex&);
double real () const { return re; }
double imag () const { return im; }
private:
double re, im;
friend complex& __doapl (complex *, const complex&);
friend complex& __doami (complex *, const complex&);
friend complex& __doaml (complex *, const complex&);
};
只有member fun后面可以用 const定義。成員變量后面不可以寫const,寫在前面。
1.1 const obj 如果調用 non-const member fun會編譯出錯
經典錯誤
如果定義時沒有寫成void print() const{}; 就會報錯。因為str是const-obj,不能用non-const member fun調用。
1.2 例子:STD里的操作符重載
來自 TEMPLATE CLASS basic_string的定義。string類的operator[]。
- 用戶可能拿[]來改變字符串。如String str[5]="a";由於string的實現機制是共享模式,不可以直接改變內部內容。只能拷貝一份再改變。所以要做cow(copy on write)設計。
- 如果const String str[2];str是const obj,其內部不可以動。所以不必考慮cow。const obj只會調用const fun,所以const fun不必寫cow。
reference operator[](size_type _Off)
{
// 下標可變序列
// 必須考慮cow
return (this->_Myptr()[_Off]);
}
const_reference operator[](size_type _Off) const
{
// 下標不可變序列
// 不必考慮cow
return (this->_Myptr()[_Off]);
}
- 可見const屬於簽名的一部分,這兩個函數可以重載。
- C++規定:如果類中有成員函數的const fun 和nonconst fun同時存在,則const obj默認調用const fun,non-const obj默認調用non-const fun。
- C++規定:non-const fun(obj可變)可以調用const fun(obj不可變)。 反過來報錯。
1.3 例子:《cpp primer》15節 -基類的定義
class Quote {
/*
** istream&:必須是非常量,因為本操作就是向流讀出數據,其狀態會改變;
** Quote& :必須是非常量,因為本操作就是向此對象寫入數據,此對象值會改變;
*/
friend istream& operator>>(istream&, Quote&);
/*
**ostream& :必須是非常量,因為本操作就是向流寫入數據,其狀態會改變;
**const Quote& :引用是因為避免賦值實參;常量是因為通常打印對象不會改變對象本身的值;
*/
friend ostream& operator<<(ostream&, const Quote&);
public:
/*這種傳遞中的代碼使用以下變量來控制編譯;
**變量:IN_CLASS_INITS/DEFAULT_FCNS;對應C++作用:類初始狀態設置/default(默認);
*/
#if defined(IN_CLASS_INITS) && defined(DEFAULT_FCNS)
//若定義類初始值設置及默認值,則定義默認構造函數,不接受任何實參;
Quote() = default;
#else
/*若未定義類初始值及默認值,則定義構造函數,函數體空;
**構造函數初始列表為新創建的數據成員price初始化,對應初始化值為 0.0;
*/
Quote() : price(0.0) { }
#endif // !defined(IN_CLASS_INITS) && defined(DEFAULT_FCNS)
//初始化構造函數
Quote(const string &book,double sales_price):
bookNo(book),price(sales_price){ }
//虛析構函數,動態綁定
#ifdef DEFAULT_FCNS
virtual ~Quote() = default;
#else
virtual ~Quote() { }
#endif // DEFAULT_FCNS
//const fun。 因為bookNo被期望是const obj,所以只能被const fun調用,必須定義為const fun,否則報錯。
string isbn() const
{ return bookNo; }
//虛函數。將在派生類中重寫,根據書的數量,采取不同的折扣算法。
//因為price(定價)也是const obj,不會被改。所以定義為const fun。
virtual double net_price(size_t n) const
{ return n*price; }//虛函數返回動態分配的自身副本
private:
const string bookNo;//書號,被期望是const obj
protected:
#ifndef IN_CLASS_INITS
const double price = 0.0;
#else
const double price;
#endif // !IN_CLASS_INITS
};