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:可以非常明确地指出通路的是調用該函數的對象的成員,且可以在成員函數中使用與資料成員同名的形參。
缺點:不必要使用,代碼多餘。