---
# System prepended metadata

title: class 類別
tags: [東華大學資管系, 資管經驗分享, 東華大學, 基本程式概念, 大一程設-下]

---

---
GA: G-RZYLL0RZGV
---

###### tags: `大一程設-下` `東華大學` `東華大學資管系` `基本程式概念` `資管經驗分享`

class 類別
===

[TOC]

## 前言
類別比較被廣泛應用於各個程式語言之中，結構是從 C 過渡到 C++ 的一個產物，在 Java、C# 裡 class 被非常廣泛的運用，學好 class 非常重要，雖然在 C++ 內的特性到其他程式語言可能有些許不同，但大觀念跟方向都非常雷同。

class 跟 structure 在 C++ 內語法可說是非常相像，所以這篇筆記就不寫太多基本語法，細部的觀念會拆分成後面的筆記來講解。

這篇主要來談論新東西 public 與 private。

> <span style="color:red">**請不要忘記 class 也是在自定義資料型態哦**</span>

## class 語法認識
```cpp=
class class_name{
public:
    member1;
    member2;
    member_function1;
    member_function2;
private:
    member3;
    member4;
    member_function3;
};
```
> 相信大家發現了兩個新的關鍵字 `public` & `private`，我們等等會來詳細的介紹他們。

我們先來看一個 class 的例子。
```cpp=
class person{
public:
    string get_name(){
        return name;
    }
    int get_age(){
        return age;
    }
    double get_salary(){
        return salary;
    }
    string get_company(){
        return company;
    }
private:
    string name;
    int age;
    double salary;
    string company;
};
```

相信上面這個例子，看過去基本上與 structure 沒有甚麼不同，都有屬性與方法。
* 屬性
    * 名字 name
    * 年紀 age
    * 薪水 salary
    * 隸屬公司 company
* 方法
    * get_name()
    * get_age()
    * get_salary()
    * get_company()

只差在新的 public 跟 private 兩個沒見過的關鍵字。所以我們來介紹他們。

## 存取修飾子 Access Modifier
### 前提先記住
> <span style="color:red; font-size:20px">**class 預設所有的 member 為 private，struct 預設所有的 member 為 public。**</span>
> [name=規定沒有為什麼]
### 設計思維
在真的談論存取修飾子之前，先來談論一些基本的程式設計思維，大家會比較有感覺。

今天大家如果想要開發一個線上購物平台 APP 讓大家來線上購物(類似蝦皮之類)，每個使用者都有一個帳號，都會用那個帳號在商城裡面逛，購買自己想要的商品，或是上架自己的商品。

<span style="color:red">**每個使用者**</span>都有自己的帳號、密碼、使用者名稱，自己管理的商場等等的內容，每個人的帳號彼此獨立互不相干。

而有一些比較隱私的內容，別人沒辦法存取，你沒辦法去取得別人的密碼，或是管理你沒有權限的商場。

而有些東西大家可以存取，你可能會關注某一個商場，比方某某品牌的服飾店，而這個服飾店可能其他人也都有在關注他。你可以透過進入這個商場去瀏覽店家上架的商品。

透過上面簡單的描述你應該可以看到，你可以瀏覽大家<span style="color:red">**公開**</span>的內容，但<span style="color:red">**隱私**</span>的內容，只有自己可以存取。

那我想關鍵字已經帶出來了!
* 公開 = <span style="color:red">public</span>
* 隱私 = <span style="color:red">private</span>

所以對於服飾店而言，讓大家瀏覽他的商品是店家<span style="color:red">**公開**</span>的資訊，但比方說一個商品的價格是多少，除了商家主人沒有人能夠去修改，大家只能夠觀看而已。

相信到了這裡存取修飾子的核心概念已經深入你心了，就是身為一個開發者，哪些東西能夠被大家存取，哪些東西只能夠被自己存取，你必須要明確地訂定好權限，以防一些安全的問題。

### public、private

延續上例，我們來看一下~
```cpp=
class person{
public:
    string get_name(){
        return name;
    }
    int get_age(){
        return age;
    }
    double get_salary(){
        return salary;
    }
    string get_company(){
        return company;
    }
private:
    string name;
    int age;
    double salary;
    string company;
};

int main(){
    person p1;
    cout << "p1's name is " << p1.get_name() << endl
         << "p1's age is " << p1.get_age() << endl
         << "p1's salary is " << p1.get_salary() << endl
         << "p1's company is " << p1.get_company() << endl;
    return 0;
}
```

你可以發現對於一個 person 物件 p1 而言，他有一些內容是不想讓別人看到的，比方說名字、年紀、薪水、公司等放在 private 內的內容。有一些能夠讓大家去存取的內容如 get_name 等的 function。

所以如果你寫這樣:
```
p1.name; // error
p1.age; // error
```
因為 name 跟 age 對於 p1 而言是 private，p1 不想讓你直接取用，你不能直接去取用他，程式會報錯。

那你應該有發現，究竟誰能夠使用 private 的 member 呢?
只有<span style="color:red">**類別藍圖(class)**</span>本身，當你在定義一個藍圖的規格的時候，藍圖內可以毫無限制的使用 member 或是 member function。
所以你會發現 4、7、10、13 行能夠暢行無阻的取用屬性直接打名字，因為是在類別藍圖內，可以不用在乎權限去取用屬性或方法。

但一旦物件被實體化，都必須遵循藍圖所訂定的存取規定。

### getter & setter (取得與設定)
你應該有發現上例有一件很奇怪的事情，明明我說無法存取，然而我們還是透過了 public 的公開方法去取得了 name、age 的數值，回到上面講的故事，就是對於賣衣服的商家而言，你看的到商品的價格，但你無法修改它的價格。

所以上例來說，你可以取得 p1 的名字、年紀，但你無法修改他的值。

> 如果今天服飾店內商品的價格能夠被大家改來改去，那會出大事的對吧!
> [name=Orange]

getter & setter 就是要透過公開的方法，來讓你去修改，或是取得私有(private)屬性的值。

getter 的好處是，讓你取得我的值但你無法修改值本身(碰不到那塊記憶體)。
setter 的好處是，提供一個接口讓你去修改私有屬性。

所以我們再來延伸一下上面的例子。

```cpp=
class person{
public:
    // getter 用來取得私有屬性
    string get_name(){return name;}
    int get_age(){return age;}
    double get_salary(){return salary;}
    string get_company(){return company;}
    
    // setter 用來修改私有屬性
    void set_name(string s){name = s;}
    void set_age(int a){age = a;}
private:
    string name;
    int age;
    double salary;
    string company;
};

int main(){
    person p1;
    p1.set_name("banana");
    p1.set_age(20);
    cout << "p1's name is " << p1.get_name() << endl
         << "p1's age is " << p1.get_age() << endl;
    
    p1.set_name("orange");
    p1.set_age(21);
    cout << "p1's name is " << p1.get_name() << endl
         << "p1's age is " << p1.get_age() << endl
    return 0;
}
```
假設今天假定公司跟薪水的值無法被修改，所以沒有 setter，而名字跟年齡可以一直修改，你可以體會上面的例子嗎?

> 所以還是老話一句，<span style="color:red">**類別要怎麼設計，什麼東西要是 private 或是 public ，完全端看需求而定**</span>。完全沒有一個相對應的規則，腦袋要轉哦。
> [name=Orange]

### protected

其實還有一個存取修飾子稱為 protected，但他比較複雜一點，我放了參考連結在下面，當作補充自己讀吧~
現在還不會可以先略過。

> 如果老師上的到繼承，我會把 protected 的筆記放在繼承後面。
> [name=Orange]

## 小總結

### 資料抽象化(Abstraction)
> 定義好一個類別藍圖，就是物件導向中我們稱的資料抽象化(Abstraction)
> [name=各大神]

### 封裝(Encapsulation)
> 而這個<span style="color:red">**為類別內的屬性與方法訂定好權限(public、private、protected)這件事情，就是物件導向內的封裝(Encapsulation**)</span>
> [name=各大神]

## Reference
[protected 說明 - 受保護的（protected）成員](https://openhome.cc/Gossip/CppGossip/protectedMember.html)