# [7] 類和對象
## FAQs in section [7]:
* 7.1] 類是什么[?
* [7.2] 對象是什么?
* [7.3] 什么樣的接口是“好”的?
* [7.4] 封裝是什么?
* [7.5] C++是如何在安全性和可用性間取得平衡的?
* [7.6] 我如何才能防止其它程序員查看我的類的私有部分而破壞封裝?
* [7.7] 封裝是一種安全裝置嗎?
* [7.8] 關鍵字 struct 和 class 有什么區別?
## 7.1 類是什么?
面向對象軟件的基本組成物
類定義數據類型,就如同 C 中的結構。從計算機科學的角度來理解,類型由狀態集合和轉換這些狀態的操作集合組成。因為 `int` 既有狀態集合,也有象 `i?+?j` 或 `i++` 等這樣的操作,所以 `int` 是一種類型。同樣,類提供了一組操作集合(通常是 `public:` )和一組描述類型實例所擁有的抽象值的數據集合。
可以將 `int` 看作為一個有 operator++ 等成員函數的類。(`int` 實際并不是一個類,但是基本類似:一個類是一種類型,就如同 `int` 是一種類型)
注意: C 程序員可以將類看作為成員默認為私有的結構。但是,如果那是你對類的全部認識,那么你可能要經歷個人的思考模式的轉變了。
## 7.2 對象是什么?
和語義有關的存儲區域
當我們聲明了`int?i`,我們說:“`i`?是?`int` 類型的一個對象”。在?OO/C++?中,“對象”通常意味著“類的一個實例”。因此,類定義多個對象(實例)的可能的行為。
## 7.3 什么樣的接口是“良好”的?
提供了一個將“塊”狀的軟件簡化了的視圖,并且以“用戶”的詞匯表達的接口。(“塊”通常是一個或一組緊密相連的類;“用戶”是指其它的開發者而不是最終客戶)
* “簡化了的視圖”指隱藏不必要的細節。這樣可以減少用戶的錯誤率。
* “用戶的詞匯”意思是用戶不需要學習新的詞匯或概念,這樣可以降低用戶的學習曲線。
## 7.4 封裝是什么?
防止未被授權地訪問一些信息和功能。
節省成本的關鍵是從軟件“塊”的穩定部分中分離出可變的部分。封裝給這個“塊”安置了防火墻,它可以防止其它“塊”訪問可變的部分;其它“塊”僅僅能夠訪問穩定的部分。這樣做,當可變的部分改變后,可以防止其它“塊”被破壞。在面向對象軟件的概念中,“塊(chunk)”通常指一個或一組緊密相連的類。
“可變的部分”是實現的細節。如果“塊”是單個類,那么可變的部分通常用 `private:` 和/或 `protected:` 關鍵字來封裝。如果“塊”是一組緊密相連的類,封裝可被用來拒絕對組中全部類的訪問。繼承。
“穩定的部分”是接口。好的接口提供了一個以用戶的詞匯簡化了的視圖,并且被從外到里的設計。(此處的“用戶”是指其它開發者,而不是購買完整應用的最終用戶)。如果“塊”是單個類,接口僅僅是類的 public: 成員函數和友元,那么接口可以包括模塊中的多個類。
設計一個清晰的接口并且將實現和接口分離,只不過是允許用戶使用接口。而封裝實現可以強迫用戶使用接口。
## 7.5 C++是如何在安全性和可用性間取得平衡的?
在 C 中,封裝是通過在編輯單元或模塊中,將對象聲明為靜態來完成的。這樣做防止了其他模塊訪問靜態區域。(順便說一句,現在這種做法是被遺棄的:不要在 C++中這樣做)
不幸的是,由于沒有對一個模塊的靜態數據產生多個實例的直接支持,這種處理方法不支持數據的多個實例。在 C 中如果需要多個實例,那么程序員一般使用結構。但是很不幸,C 的結構不支持封裝。這增加了在安全性(信息隱藏)和可用性(多實例)之間取得平衡的難度。
在 C++中,你可以利用類來同時獲得多實例和封裝性。類的 public: 部分包含了類的接口,它們通常由類的 public: 成員函數和它的友元 部分包含了類的實現,而通常數據就在這里。
最終的結果就象是“封裝了的結構”。這樣就易于在安全性(信息隱藏)和可用性(多實例)間取得平衡。
## 7.6 我如何才能防止其它程序員查看我的類的私有部分而破壞封裝?
不必這么做——封裝是對于代碼而言的,而不是對人。
只要其它程序員寫的代碼不依賴于他們的所見,那么即使它們看了你的類的 `private:` 和/或 `proteced:` 部分,也不會破壞封裝。換句話說,封裝不會 阻止人認識類的內部。封裝只是防止他們寫出依賴類內部實現的代碼。你的公司不必為維護你眼睛所看到的東西支付維護成本,但是必須為維護你的指尖寫出的代碼支付維護成本。正如你知道的,倘若他們寫的代碼依賴于接口而不是實現,就不會增加維護成本。
此外,這很少成為一個問題。我想不會有故意試圖訪問類的私有部分的程序員。My recommendation in such cases would be to change the programmer, not the code" [[James Kanze](mailto:kanze@gabi-soft.fr); used with permission].
## 7.7 封裝是一種安全裝置嗎?
不。
封裝 != 安全。
封裝要防止的是錯誤,而不是間諜。
## 7.8 關鍵字 struct 和 class 有什么區別?
struct 的成員默認是公有的,而類的成員默認是私有的。注意:你應該明白地聲明你的類成員為公有的、私有的、或者是保護的,而不是依賴于默認屬性
struct 和 class 在其他方面是功能相當的。
OK,明晰的技術談論夠多了。從感情上講,大多數的開發者感到類和結構有很大的差別。感覺上結構僅僅象一堆缺乏封裝和功能的開放的內存位,而類就象活的并且可靠的社會成員,它有智能服務,有牢固的封裝屏障和一個良好定義的接口。既然大多數人都這么認為,那么只有在你的類有很少的方法并且有公有數據(這種事情在良好設計的系統中是存在的!)時,你也許應該使用 struct 關鍵字,否則,你應該使用 class 關鍵字。?
- C++ FAQ Lite
- [1] 復制許可
- [2] 在線站點分發本文檔
- [3] C++-FAQ-Book 與 C++-FAQ-Lite
- [6] 綜述
- [7] 類和對象
- [8] 引用
- [9] 內聯函數
- [10] 構造函數
- [11] 析構函數
- [12] 賦值算符
- [13] 運算符重載
- [14] 友元
- [15] 通過 <iostream> 和 <cstdio>輸入/輸出
- [16] 自由存儲(Freestore)管理
- [17] 異常和錯誤處理
- [18] const正確性
- [19] 繼承 — 基礎
- [20] 繼承 — 虛函數
- [21] 繼承 — 適當的繼承和可置換性
- [22] 繼承 — 抽象基類(ABCs)
- [23] 繼承 — 你所不知道的
- [24] 繼承 — 私有繼承和保護繼承
- [27] 編碼規范
- [28] 學習OO/C++
- [31] 引用與值的語義
- [32] 如何混合C和C++編程
- [33] 成員函數指針
- [35] 模板 ?
- [36] 序列化與反序列化
- [37] 類庫