---
# System prepended metadata

title: 【C++ 筆記】資料抽象與 ADT - part 25
tags: [物件導向程式設計, 程式設計, C++, 程式語言, OOP]

---

【C++ 筆記】資料抽象與 ADT - part 25
===

目錄（Table of Contents）：

[TOC]

---

很感謝你點進來這篇文章。

你好，我並不是什麼 C++、程式語言的專家，所以本文若有些錯誤麻煩請各位鞭大力一點，我極需各位的指正及指導！！本系列文章的性質主要以詼諧的口吻，一派輕鬆的態度自學程式語言，如果你喜歡，麻煩留言說聲文章讚讚吧！

簡介
---

> Data abstraction refers to providing only essential information about the data to the outside world, ignoring unnecessary details or implementation.
> From GeeksForGeeks

資料抽象指的是只提供外界所必要的資訊，忽略不必要的細節或實作面。

什麼意思呢？就像你在玩遊戲時，可以看到角色的 HP、MP 等資訊，但你不需要知道這些數值是怎麼計算的、存在哪個記憶體位址、或者用什麼資料結構去記錄這些資訊。

遊戲開發者只會讓你看到角色的重要狀態資訊，而把它的具體表示方法（如 class 的欄位、加密編碼或計算過程）藏起來，這就是資料抽象。

### 資料抽象的優點

1. 簡化：
    
    前面有說到資料抽象可以隱藏內部實作細節，只提供必要的介面，讓程式設計易懂、易管理。user 不用去關心物件如何運作，只需透過公開的介面使用功能。
2. 程式碼的可維護性：
    
    因為內部實作細節被封裝起來，修改類別的內部結構或演算法時，只要保持介面不變，外部 user 的程式碼不需改動，減少了維護成本和錯誤風險。
3. 保護資料完整性：

    將資料成員設為 private，防止外部直接修改，避免因誤用導致物件狀態不一致或錯誤，提升程式的安全性和穩定性。
4. 可使程式碼重複使用：

    資料抽象使得類別設計更具模組化，可以在不同專案或上下文中重複使用相同的抽象類別或介面，提高開發效率。

### 標頭檔也有資料抽象

如 `<algorithm>` 裡面的 `sort()`，不需要知道他是用什麼排序法去寫的，你只要呼叫這個函式，參數填一填，他就可以用了。（[菜鳥教程](https://www.runoob.com/cplusplus/cpp-data-abstraction.html)）

另外一個例子是 `<cmath>`，裡面的 `pow()` 函式，也不用知道中間演算的過程，反正呼叫這函式就可以用了。（[GeeksForGeeks](https://www.geeksforgeeks.org/cpp/abstraction-in-cpp/)）

### 封裝與抽象

兩者概念很像，但實際上還是有差別。

抽象只是程式設計的設計概念，而封裝是實現抽象的技術手段（如用存取修飾子控制外部權限存取）。

資料抽象之實作方式
---

當然就是使用 class 了，class 將資料（成員變數）和操作資料的函式（成員函式）封裝在一起，並透過存取修飾詞（public、private、protected）控制外部對資料的存取權限。

* public：公開介面，外部程式可以存取。
* private：私有成員，外部無法直接存取，隱藏實作細節。
* protected：受保護成員，僅限類別本身及其衍生類別存取。

在此之前，要再說明一個觀念是 ADT（Abstraction Data Type），資料抽象型態，在 C++ 中的類別都是屬於 ADT 的實作。

> An Abstract Data Type (ADT) is a conceptual model that defines a set of operations and behaviors for a data structure, without specifying how these operations are implemented or how data is organized in memory.
> From GeeksForGeeks

資料抽象型態是一種概念模型，為資料結構定義了一組操作和行為，而不指定這些操作如何實現或資料如何在記憶體中組織。

以下有兩個例子，都同屬於 AD、ADT 的範疇：

```cpp=
// account.cpp
#include <iostream>
using namespace std;

class BankAccount {
private:
    int balance;

public:
    BankAccount() {
        balance = 0;
    }

    void deposit(int amount) {
        if (amount > 0)
            balance += amount;
    }

    void withdraw(int amount) {
        if (amount <= balance)
            balance -= amount;
    }

    int getBalance() {
        return balance;
    }
};

int main() {
    BankAccount account;
    account.deposit(1000);
    account.withdraw(300);
    cout << "目前餘額：" << account.getBalance() << endl;
    return 0;
}
```

```cpp=
// door.cpp
#include <iostream>
using namespace std;

class Door {
private:
    bool isOpen;

public:
    Door() {
        isOpen = false;
    }

    void open() {
        isOpen = true;
    }

    void close() {
        isOpen = false;
    }

    bool status() {
        return isOpen;
    }
};

int main() {
    Door d;
    d.open();
    cout << "門的狀態：" << (d.status() ? "開啟" : "關閉") << endl;
    return 0;
}
```

首先資料抽象在哪：

- account.cpp：user 可用 deposit()、withdraw()、getBalance() 成員函式，而不需要知道 balance 是如何運作的。
- door.cpp：user 可用 open()、close() 成員函式去控制門的開關，不用知道 isOpen 他是什麼 bool 變數，怎麼運作的等等。

上述的 balance、isOpen 都用到 private 存取修飾子控制權限，只有 class 內部可以使用，外部無法存取。

那 ADT 呢？

根據 ADT 的定義，在上述兩個範例中有以下 ADT 的 features：

1. 定義一組資料：有 balance、isOpen。
2. 定義一組操作：deposit()、withdraw()、getBalance()、open()、close()。
3. 隱藏實作細節：透過封裝的方式讓 user 無法直接操作資料，只能透過介面（像是由開發者所提供的成員函式 deposit() 等）去操作。
4. 資料結構的獨立性：就算用不同資料結構去做這些事情，介面一樣不會變。

:::info
ADT features：
- Abstraction（抽象）
- Better Conceptualization（更佳的概念化）
- Robust（茁壯性，程式能有效捕捉到錯誤）
- Encapsulation（封裝）
- Data Abstraction
- Data Structure Independence
- Information Hiding
- Modularity（模組化）

From GeeksForGeeks
:::

ADT 的經典例子
---

那些常見的資料結構如：

1. 鏈結串列 list
2. 堆疊 stack
3. 佇列 queue

同屬於 ADT。

這邊就舉 stack 跟 queue 當例子，why？因為實作起來比較簡單，~~我恨 list~~。

```cpp=
// stack.cpp
#include <iostream>
#include <vector>
using namespace std;

class Stack {
private:
    vector<int> data;

public:
    void push(int x) {
        data.push_back(x);
    }

    void pop() {
        if (!data.empty()) data.pop_back();
    }

    int top() {
        return data.back();
    }

    bool isEmpty() {
        return data.empty();
    }
};
```

```cpp=
// queue.cpp
#include <iostream>
#include <vector>
using namespace std;

class Queue {
private:
    vector<int> data;
    int frontIndex;

public:
    Queue() {
        frontIndex = 0;
    }

    void enqueue(int x) {
        data.push_back(x);
    }

    void dequeue() {
        if (!isEmpty()) {
            frontIndex++;
        }
    }

    int front() {
        if (!isEmpty()) {
            return data[frontIndex];
        } else {
            // cpp 例外處理語法
            throw out_of_range("Queue is empty");
        }
    }

    bool isEmpty() {
        return frontIndex >= data.size();
    }

    int size() {
        return data.size() - frontIndex;
    }
};

int main() {
    Queue q;
    q.enqueue(10);
    q.enqueue(20);
    q.enqueue(30);

    cout << "front : " << q.front() << endl;
    q.dequeue();

    cout << "front : " << q.front() << endl;
    q.dequeue();

    cout << "Is queue empty : " << (q.isEmpty() ? "y" : "n") << endl;
    q.dequeue();

    cout << "Is queue empty : " << (q.isEmpty() ? "y" : "n") << endl;

    return 0;
}
```

總結
---

### 資料抽象（Data Abstraction）概念

資料抽象是指只向外界提供必要的資料資訊，隱藏不必要的細節和實作方式。如遊戲中玩家只看到角色的HP、MP 等狀態，不用知道這些數值如何計算或存放在記憶體的哪裡。開發者透過類別（class）封裝內部資料與操作，並只公開必要的介面給使用者，達成資料抽象。

### 資料抽象的優點

- 簡化程式設計：隱藏內部實作細節，只暴露必要介面，讓使用者專注於功能使用，讓程式可讀性提升也好管理。
- 提高可維護性：內部實作可變更而不影響外部使用者，只要介面不變，減少維護成本與錯誤風險。
- 保護資料完整性：將資料成員設為 private，避免外部直接修改，防止狀態不一致或錯誤，提升安全性與穩定性。
- 促進程式碼重用：抽象類別設計模組化，能在不同專案或上下文中重複使用，提高開發效率。

### 封裝與抽象的關係

抽象是設計概念，強調「做什麼」而非「怎麼做」。

封裝是實現抽象的技術手段，利用存取修飾子（public、private、protected）控制資料存取權限，隱藏實作細節。

### 抽象資料型態（Abstract Data Type, ADT）

ADT 是一種概念模型，定義一組資料和操作行為，但不規定其內部實作或資料組織方式。C++ 中的類別都是屬於 ADT 的實作。ADT 的特性包括：

- 定義資料集合（如 balance、isOpen）
- 定義操作行為（如 deposit()、withdraw()、open()、close()）
- 隱藏實作細節，使用者只能透過介面操作資料
- 資料結構獨立性，內部實作可變更但介面不變。

ADT 的經典例子含鏈結串列（list）、堆疊（stack）、佇列（queue）等。

參考資料
---

[單元二 資料抽象化 Data Abstraction - HackMD](https://hackmd.io/@Derek46518/BkqWS_Hmj)

[Data Structure 資料結構 - Abstraction 抽象化 | by Fion Yu | Minds | Medium](https://medium.com/fion-minds/data-structure-%E8%B3%87%E6%96%99%E7%B5%90%E6%A7%8B-abstraction-%E6%8A%BD%E8%B1%A1%E5%8C%96-511ed86fbd1c)

[Abstract Data Types - GeeksforGeeks](https://www.geeksforgeeks.org/abstract-data-types/)

[Abstraction in C++ - GeeksforGeeks](https://www.geeksforgeeks.org/cpp/abstraction-in-cpp/)

[C++ 数据抽象 | 菜鸟教程](https://www.runoob.com/cplusplus/cpp-data-abstraction.html)