## 第7章 類
### 7.1.2
- 定義在類內部的函數都是隱式的inline函數。
- 在成員函數的聲明中,緊跟在參數列表之后的**const**表示**this**是一個指向常量的指針。這樣的成員函數被稱作常量成員函數。常量對象,以及常量對象的引用或指針都只能調用常量成員函數。
- 編譯器分兩步處理類:首先編譯成員的聲明,然后編譯成員函數體。
- 返回this對象:
```cpp
return *this; //返回調用該函數的對象
```
### 7.1.3
一般來說,如果非成員函數是類接口的組成部分,則這些函數的聲明應該與類在同一個頭文件內。
### 7.1.4
- 構造函數不能被聲明成const的。
- 只有當類沒有聲明任何構造函數時,編譯器才會自動地生成默認構造函數,此時必須定義一個默認構造函數。
- 如果類中包含一個其他類類型的成員且這個成員的類型沒有默認構造函數,那么編譯器將無法初始化該成員,即無法合成默認的構造函數。
- 在C++11新標準中,如果我們需要默認的行為,那么可以通過在參數列表后面寫上`= default`來要求編譯器生成構造函數。
### 7.1.5
需要動態內存的類應盡量使用vector對象或者string對象管理必要的存儲空間,這樣能避免分配和釋放內存帶來的復雜性。
### 7.2 訪問控制與封裝
使用**class**定義類時,默認訪問權限是**private**;使用**struct**定義類時,默認訪問權限是**public**。
### 7.2.1
- 友元不是類的成員,也不受它所在區域訪問控制級別的約束。
- 友元聲明并非通常意義上的函數聲明。通常建議在友元聲明之外再專門對函數進行一次聲明。
### 7.3.1
- 類中用來定義類型的成員必須先定義后使用。
- inline成員函數應與相應的類**定義**在同一個頭文件中。
- **mutable**聲明無視const
一個可變數據成員(mutable data member)永遠不會是const,即使它是const對象的成員。因此,一個const成員函數可以改變一個可變成員的值。
### 7.3.3
不完全類型(incomplete type)的類只能在以下有限情景中使用:
- 可以定義指向這種類型的指針或引用
- 可以聲明(但是不能定義)以其作為參數或者返回類型的函數
### 7.3.4
友元關系不存在傳遞性。
### 7.4.1
編譯器處理完類中的全部聲明后才會處理成員函數的定義。
### 7.5.1
- 類成員的初始化順序與它們在類定義中的出現順序一致。構造函數初始化列表中初始值的前后位置關系不會影響實際的初始化順序。
- 如果一個構造函數為所有參數都提供了默認實參,則它實際上也定義了默認構造函數。
### 7.5.2 委托構造函數(delegating constructor, C++11)
當一個構造函數委托給另一個構造函數時,受委托的構造函數的初始值列表和函數體被依次執行。然后控制權交還委托者的函數體。
### 7.5.4
- 如果構造函數只接受一個實參,則它實際上定義了轉換為此類類型的隱式轉換機制,有時我們把這種構造函數稱作**轉換構造函數**。
- 通過在類內聲明處添加**explicit**聲明可以抑制構造函數定義的隱式轉換,不允許在類外聲明或定義時出現。使用explicit聲明的構造函數只能以直接初始化的形式使用,而不能以拷貝初始化的形式使用。
- 練習7.4,7.5,7.9,7.15,7.22,7.50
```cpp
/* 文件名:Person.h */
/* C++ Primer中文版第5版, 第7章系列練習 */
/* 主要內容: 類的基礎知識 */
/* 日期:2017-09-18 */
#ifndef _PERSON_H_
#define _PERSON_H_
#include <iostream>
#include <string>
class Person{
friend std::istream &readPerson(std::istream &is, Person &person);
friend std::ostream &printPerson(std::ostream &os, Person &person);
public:
Person() = default;
Person(const std::string &name_, const std::string &addr_) : name(name_), addr(addr_) {}
explicit Person(std::istream &is) { readPerson(is, *this); }
std::string name() const { return this->name; }
std::string addr() const { return this->addr; }
private:
std::string name;
std::string addr;
};
std::istream &readPerson(std::istream &is, Person &person)
{
is >> person.name >> person.addr;
return is;
}
std::ostream &printPerson(std::ostream &os, Person &person)
{
os << person.name << " " << person.addr;
return os;
}
#endif
```
### 7.6 類的靜態成員
- 靜態成員函數不能聲明成const的,也不能在函數體內(無論是顯式地或者隱式地)使用this指針。但成員函數不用通過作用域運算符就能直接使用靜態成員。
- 靜態成員函數只能在類內部使用static聲明,不能在類外部定義時重復該關鍵字。
- 通常情況下應該在類的外部定義和初始化每個靜態成員。如果在類的內部提供了一個初始值,則類外對成員的定義不能再指定初始值。
- 靜態數據成員可以是**不完全類型**,靜態數據成員的類型可以是它所屬的類類型。靜態成員可以作為默認實參。