C++聲明之CV限定符


目錄

1.const

1.1 const obj 如果調用 non-const member fun會編譯出錯

經典錯誤

1.2 例子:STD里的操作符重載

1.3 例子:《cpp primer》15節 -基類的定義


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
};

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM