天天看點

C++Primer第五版 第七章習題答案(21~30)

21.22:通常的做法是将相關變量定義為private,而接口函數定義為public。具體情況具體讨論

23:知識點1:類可以自定義某種類型在類中的别名—通過typedef和using

知識點2:如果我們需要合成的預設構造函數,在空清單的構造函數後加上=default即可

知識點3:類的成員也可以重載,參數清單數量或者類型上不同

知識點4:在變量前加關鍵字mutable,變為可變資料成員,即使是在一個const的對象函數中也可以被修改

知識點5:類内初始值,直接用=賦予的方式是C++11新特性,也就是VS2013以上的版本才支援

知識點6:當某個資料成員在構造函數初始化清單中忽略,它将以預設構造函數的方式隐式初始化

#ifndef Cccc//第一次包含本頭檔案時,#ifndef判斷為真,預處理器将處理後面的内容直到#endif,此時的預處理變量Cccc已定義
#define Cccc//第二次包含本頭檔案時,#ifndef判斷為假,預處理器将忽略後面的内容

#include <string>

class Screen {
public:
	using pos = std::string::size_type;//std庫中的string類的sizetype類型

	Screen() = default;
	Screen(pos ht, pos wd, char c) : height(ht), width(wd), contents(ht * wd, c)
	{
	}

	char get() const { return contents[cursor]; }
	char get(pos r, pos c) const { return contents[r * width + c]; }

private:
	pos cursor = 0;
	pos height = 0, width = 0;
	std::string contents;
};

#endif//隻要簡單的加上就好了,無視C++中的作用域規則,作用是防止頭檔案被重複包含

/*
c++ string::size_type詳解   
	string::size_type類型   
	從邏輯上來講,size()成員函數似乎應該傳回整型數值,或如2.2節“建議”中所述的無符号整數。但事實上,size操作傳回的是string::size_type類型的值。
	我們需要對這種類型做一些解釋。string類類型和許多其他庫類型都定義了一些夥伴類型(companion types)。這些夥伴類型使得庫類型的使用是機器無關的(machine-independent)。
	size_type就是這些夥伴類型中的一種。它定義為與unsigned型(unsigned int或unsigned long)具有相同的含義,而且可以保證足夠大可存儲任意string對象的長度。
	為了使用由string類型定義的size_type類型,程式員必須加上作用域操作符來說明所使用的size_type類型是由string類定義的。  
	任何存儲string的size操作結果的變量必須為string::size_type類型。特别重要的是,不要把size的傳回值賦給一個int變量。  
	雖然我們不知道string::size_type的确切類型,但可以知道它是unsigned型(2.1.1節)。對于任意一種給定的資料類型,它的unsigned型所能表示的最大正數值比對應的signed要大一倍。
	這個事實表明size_type存儲的string長度是int所能存儲的兩倍。  
	使用int變量的另一個問題是,有些機器上int變量的表示範圍太小,甚至無法存儲實際并不長的string對象。如在有16位int型的機器上,int類型變量最大隻能表示32767個字元的string對象。
	而能容納一個檔案内容的string對象輕易就會超過這個數字。是以,為了避免溢出,儲存一個string對象size的最安全的方法就是使用标準庫類型string:: size_type。  


	string類類型和許多其他庫類型都定義了一些配套類型(companion type)。通過這些配套類型,庫類型的使用就能和機器無關(machine-independent)。string::size_type定義為unsigned型,可以保證足夠大的存儲string對象的長度。  

	注意,任何存儲string的size操作結果的變量必須為string::size_type類型。尤其不能把size的傳回值賦給一個int變量。(因為size傳回的是一個unsigned類型,而int是signed類型。size能表達的大小是int的2倍)。  

string str("some string");   //通過字元串字面值指派給串  
for (string::size_type ix = 0; ix != str.size(); ++ix)   //此處不該為int     用!=,而不用<=  
{  
	cout<<str[ix]<<endl;  
}  

vector<int> ivec;  
for(vector<int>::iterator ix = ivec.begin(); ix != ivec.end(); ++ix)     
	//此處不該為int     用!=,而不用<=  
{  
	*ix = 0; //将各個元素指派為0  
}  

綜上所述:string::size_type 等價于 unsigned ,使用情況為存儲字元串的大小
*/
           

24:

Screen() = default; // 1
Screen(pos ht, pos wd) : height(ht), width(wd), contents(ht * wd, ' ') {} // 2
Screen(pos ht, pos wd, char c) : height(ht), width(wd), contents(ht * wd, c)
{
} // 3
           

其他同上

25:隻有内置類型和string類型可以依賴于操作的預設版本

26:在類體外定義直接加inline即可,體内聲明為inline也可,但要保持一緻。

27:知識點:傳回引用的函數為左值,傳回*this的函數,傳回本函數修改後的對象本身而非對象的副本。這樣的話就會出現函數的重複使用,如下:

myScreen.move(4, 0).set('#').display(std::cout);
//move()和display()函數可以互相調用,因為他們的傳回值是對象的本身,該對象就是myScreen,move()和dispaly()函數對myScerrn執行不同的操作
           

28:知識點:若函數傳回類型變為Screen,則傳回的是對象的副本,函數的操作隻能添加于對象的副本上,對象的本身并沒有改變。

此題中,myScreen本身并不會被三個函數所改變,是以不會輸出“#”

29:正确

30:優點:

1:當需要将一個對象作為整體引用而不是引用對象的一個成員時,使用this,則該函數傳回對調用該函數的對象的引用。 

2:可以非常明确地指出通路的是調用該函數的對象的成員,且可以在成員函數中使用與資料成員同名的形參。  

缺點:不必要使用,代碼多餘。

繼續閱讀