首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> C語言 >> C++ >> 關於C++

C++ 類與對象實戰:五個經典封裝練習完整解析

     編輯:關於C++

面向對象封裝核心原則

類的封裝性要求:數據成員私有化,操作介面公有化。通過 `private` 隱藏內部實現細節,通過 `public` 成員函數提供受控訪問,實現數據抽象與信息隱藏。

練習 1:Person 類 — 基礎封裝與多構造方式

需求

  • 屬性:`name` (char[5])、`age` (int)、`sex` (char)
  • 方法:`Register()` 初始化、`ShowMe()` 顯示
  • 兩種對象創建方式:`cin` 輸入、`Register("Zhang3", 19, 'm')` 直接調用

關鍵實現

class Person {
private:
    char name[5];
    int age;
    char sex;
public:
    void Register(const char* _name, int _age, char _sex) {
        strncpy(name, _name, 4); name[4] = '\0'; // 防溢出
        age = _age; sex = _sex;
    }
    void ShowMe() const { // const 成員函數:不修改對象狀態
        cout << name << ' ' << age << ' ' << sex << endl;
    }
};

int main() {
    Person p1, p2;
    p2.Register("Zhang3", 19, 'm'); // 直接初始化
    
    char name[5]; int age; char sex;
    cin >> name >> age >> sex;
    p1.Register(name, age, sex);    // 輸入初始化
    
    p1.ShowMe(); p2.ShowMe();
    return 0;
}

考點

  • 字符數組邊界保護 (`strncpy` + 手動結尾)
  • `const` 成員函數正確性
  • 同一類對象的多種初始化路徑

練習 2:Dog 類 — 存取器模式與格式化輸出

需求

  • 屬性:`name`、`age`、`sex`、`weight`
  • 方法:`setdata()` 初始化、四個 `GetXxx()` 存取器
  • 嚴格格式化輸出,句末有句號

關鍵實現

class Dog {
private:
    char name[20]; int age; char sex; float weight;
public:
    void setdata(const char* n, int a, char s, float w) {
        strncpy(name, n, 19); name[19] = '\0';
        age = a; sex = s; weight = w;
    }
    void GetName() const { cout << "Its name is " << name << ".\n"; }
    void GetAge() const { cout << "It is " << age << " years old.\n"; }
    void GetSex() const { 
        cout << "It is " << (sex == 'm' ? "male" : "female") << ".\n"; 
    }
    void GetWeight() const { cout << "It is " << weight << " kg.\n"; }
};

考點

  • 存取器方法命名規範
  • 條件運算符處理性別顯示
  • 輸出格式精確控制

練習 3:Trapezium 類 — 幾何計算與座標封裝

需求

  • 屬性:梯形四頂點座標 (x1,y1)...(x4,y4),上下底平行 x 軸
  • 方法:`initial()` 初始化、`GetPosition()` 讀取、`Area()` 計算面積
  • 面積公式:`(上底 + 下底) × 高 / 2`

關鍵實現

class Trapezium {
private:
    int xul, yul, xur, yur, xdl, ydl, xdr, ydr; // 左上、右上、左下、右下
public:
    void initial(int _xul, int _yul, int _xur, int _yur,
                 int _xdl, int _ydl, int _xdr, int _ydr) {
        xul=_xul; yul=_yul; xur=_xur; yur=_yur;
        xdl=_xdl; ydl=_ydl; xdr=_xdr; ydr=_ydr;
    }
    void GetPosition(int& a, int& b, int& c, int& d,
                     int& e, int& f, int& g, int& h) const {
        a=xul; b=yul; c=xur; d=yur; e=xdl; f=ydl; g=xdr; h=ydr;
    }
    void Area() const {
        // 上底 = xur - xul, 下底 = xdr - xdl, 高 = yul - ydl (假設 yul > ydl)
        float area = (float)(xur - xul + xdr - xdl) * (yul - ydl) / 2;
        cout << area << endl;
    }
};

考點

  • 引用參數實現「輸出參數」語義
  • 整數運算轉浮點避免精度丟失
  • 幾何模型與座標系統的對應關係

練習 4:MyTime 類 — 時間制轉換與格式化

需求

  • 方法:`SetTime()` 設置、`print_12()` 12小時制、`print_24()` 24小時制
  • 12小時制規則:0:00→12:00 AM,12:00→12:00 PM,13:00→01:00 PM
  • 輸出格式:`HH:MM:SS AM/PM`,雙位數補零

關鍵實現

class MyTime {
private:
    int h, m, s; // 內部統一用 24 小時制存儲
public:
    void SetTime(int _h, int _m, int _s) { h=_h; m=_m; s=_s; }
    
    void print12() const {
        int h12 = (h % 12 == 0) ? 12 : h % 12; // 0/12 都顯示 12
        bool isPM = (h >= 12);
        cout << setw(2) << setfill('0') << h12 << ':'
             << setw(2) << setfill('0') << m << ':'
             << setw(2) << setfill('0') << s << ' '
             << (isPM ? "PM" : "AM") << endl;
    }
    
    void print24() const {
        cout << setw(2) << setfill('0') << h << ':'
             << setw(2) << setfill('0') << m << ':'
             << setw(2) << setfill('0') << s << endl;
    }
};

考點

  • <iomanip> 的 `setw`/`setfill` 實現零填充
  • 模運算處理 12/24 小時制轉換邏輯
  • 邊界情況:午夜 0:00 和中午 12:00 的特殊處理

練習 5:Weekday 類 — 循環枚舉與模運算

需求

  • 輸入 0-6 代表 週日-週六
  • 方法:`SetDay()`、`IncDay()` 前進一天、`NowDay()` 中文輸出
  • 連續輸出 3 天(循環)

關鍵實現

class Weekday {
private:
    int today; // 0-6
public:
    void SetDay(int d) { today = (d % 7 + 7) % 7; } // 歸一化
    void IncDay() { today = (today + 1) % 7; }
    void NowDay() const {
        static const char* names[] = {"星期日","星期一","星期二","星期三","星期四","星期五","星期六"};
        cout << names[today] << endl;
    }
};

int main() {
    Weekday w; int d; cin >> d;
    w.SetDay(d);
    w.NowDay(); w.IncDay(); w.NowDay(); w.IncDay(); w.NowDay();
    return 0;
}

考點

  • 靜態字符串陣列避免 switch 冗長
  • 模運算實現循環邏輯
  • 輸入歸一化防禦性編程

五大練習共同考察的核心能力

能力點體現練習
私有數據 + 公有介面全部
構造/初始化函數設計Person, Dog
const 正確性Person::ShowMe, Dog::GetXxx
字符串安全處理Person, Dog (strncpy)
引用參數作為輸出Trapezium::GetPosition
格式化輸出控制Dog, MyTime
邊界條件處理MyTime (0/12點), Weekday (模7)
靜態數據成員優化Weekday::names

進階改進建議

  1. 使用構造函數替代 `Register`/`setdata`:符合 RAII 原則,對象創建即初始化完成
  2. 引入 `std::string` 替代字符數組:避免緩衝區溢出,簡化內存管理
  3. 運算符重載:`operator<<` 用於輸出,`operator++` 用於 `IncDay`
  4. 異常處理:無效輸入拋出 `std::invalid_argument`
  5. 單元測試:使用 Google Test 驗證邊界條件

總結

這五個練習系統性覆蓋了 C++ 類設計的核心場景:基礎封裝、存取器模式、幾何計算、時間處理、枚舉循環。掌握「數據私有、介面公有、const 正確、邊界防禦、格式精確」這五大原則,配合現代 C++ 特性(`std::string`、``、構造函數初始化列表),能寫出健壯、可維護、符合工業標準的類代碼。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved