類和封裝的概念
類和封裝的概念
什麽是類?
電腦一般而言是由CPU,內存,主板,鍵盤和硬盤等部件組合而成。
思考:學習電腦組裝需要多少時間?學習電腦組裝是都需要學習顯示器,鍵盤,鼠標,主板等部件的設計與制造?
類的封裝
我們可以把程序按某種規則分成很多"塊",類與類之間可能會有聯系,每個類都有一個可變部分(public)和一個不可變部分(private)。我們需要把可變部分和不可變部分分離出來,將不可變的部分暴露給其他類,而將可變的部分隱藏起來,以便於隨時可以讓它修改。這項工作就是封裝。
類分為以下兩個部分
- 類的實現細節
- 類的使用方式
類為什麽需要封裝
- 當使用類時,不需要關心其實現細節。當我們創建類時,才需要考慮其內部實現細節。
例如:普通用戶使用手機,只需要學習如何發短信,打電話,拍照等等。而這些功能如何實現,則是手機開發工程師需要考慮的事情。
- 高內聚,低耦合移植時我們所追求的,用好封裝恰恰可以減少耦合
- 只要對外接口不改變,可以任意修改內部實現,這個可以很好的應對變化。
- 類具有了簡潔清晰的對外接口,降低使用者的學習過程。
如何將一個類封裝
- 根據經驗:並不是類的每個屬性都是對外公開的
- 如:女孩子不希望外人知道自己的體重和年齡
- 如:男孩子不希望別人知道自己的身高和收入
- 而一些類的屬性是對外公開的
- 如:人的姓名,學歷,國籍等
- 必須在類的表示法中定義屬性和行為的公開級別
- 類似文件系統中文件的權限
C++中類的封裝
- 成員變量:C++中用於表示類屬性的變量
- 成員函數:C++中用於表示類行為的函數
- C++中可以給成員變量和成員函數定義訪問級別
- public
成員變量和成員函數可以在類的內部和外界訪問和調用
- private
成員變量和成員函數只能在類的內部被訪問和調用
示例代碼:類成員的訪問屬性
struct Human { void sleep() { printf("I‘m sleeping...\n"); }
void work() { printf("I‘m working...\n"); } };
struct Girl : Human { private: int age; int weight; public: void print() { age = 22; weight = 48;
printf("I‘m a girl, I‘m %d years old.\n", age); printf("My weight is %d kg.\n", weight); } };
struct Boy : Human { private: int height; int salary; public: int age; int weight;
void print() { height = 175; salary = 9000;
printf("I‘m a boy, my height is %d cm.\n", height); printf("My salary is %d RMB.\n", salary); } };
int main() { Girl girl; Boy boy; Human human;
human.sleep();
girl.print();
boy.age = 19; boy.weight = 120; boy.height = 180; //Error: ‘int Boy::height‘ is private
boy.print();
boy.work();
return 0; } |
分析:
- 從我們通過boy.height = 180;修改boy對象中的身高的值時,編譯時會產生錯誤。提示我們Boy::height這個成員變量是私有的。但是我們卻可以在boy.printf()函數中修改height的值。所以我們可以知道:private的成員只能在類的內部被訪問和調用
- 我們通過boy.age = 19;編譯時並沒有發生錯誤可以知道。類的public成員可以在類的外部修改,所以public的成員可以在類的內部和外界訪問和調用
- 我們在Human這個類中沒有明顯定義類的成員屬於private還是屬於public,但是我們在main中調用它編譯沒有報錯。說明struct定義的類默認為public的。
- 我們可以在boy中使用Human類中的函數work();
類成員的作用域
我們知道全局變量和局部變量都有作用域,那麽類也有作用域嗎?
示例代碼:類成員的作用域
#include <stdio.h>
int i = 1;
struct Test { private: int i;
public: int j;
int getI() { i = 3;
return i; } };
int main() { int i = 2;
Test test;
test.j = 4;
printf("i = %d\n", i); // i = 2; printf("::i = %d\n", ::i); // ::i = 1; // printf("test.i = %d\n", test.i); // Error printf("test.j = %d\n", test.j); // test.j = 4 printf("test.getI() = %d\n", test.getI()); // test.getI() = 3
return 0; } |
分析:
- 我們單純打印printf("i = %d\n", i); i的變量是main函數內定義的i的值,而不是全局變量i=4的值。這是因為小範圍作用域的值會覆蓋大範圍作用域的值。
- 我們使用::作用域解析運算符來使用默認全局變量i的值。
- 我們訪問Test類中成員時,不能從外部直接訪問類的成員,公有成員變量和成員函數也是不能直接訪問,需要通過對象才能訪問類的成員。如代碼所示:訪問類成員i變量,需要定義一個test對象,通過test對象才能訪問i的值。
- 類成員的作用域都只在類的內部,外部無法直接訪問。也就是說不同類中使用相同的類成員名不會發生沖突。實際上類與命名空間有點相像。
類和封裝的概念