第8天:面向對象編程入門 - 類與對象
一、📚 今日學習目標
- 🎯 掌握類與對象的定義與使用
- 🔧 理解封裝、繼承、多態三大特性
- 💡 完成銀行賬戶管理系統實戰
- 🛠? 學會構造函數與析構函數的編寫
二、?? 核心知識點詳解
1. 類的定義與對象創建
類的基本結構
class BankAccount {
private:string accountNumber;double balance;public:// 構造函數BankAccount(string accNo, double initialBalance) : accountNumber(accNo), balance(initialBalance) {}// 成員函數void deposit(double amount) {balance += amount;}bool withdraw(double amount) {if (balance >= amount) {balance -= amount;return true;}return false;}double getBalance() const {return balance;}
};// 創建對象
BankAccount myAccount("123456", 1000.0);
2. 封裝與訪問控制
成員訪問修飾符
class Person {
public: // 公有成員string name;
protected: // 受保護成員int age;
private: // 私有成員string idCard;
};
3. 繼承與多態
繼承語法
class SavingsAccount : public BankAccount {
private:double interestRate;public:SavingsAccount(string accNo, double initialBalance, double rate): BankAccount(accNo, initialBalance), interestRate(rate) {}void addInterest() {balance += balance * interestRate / 100;}
};
三、🔧 代碼實戰:銀行賬戶管理系統
1. 功能需求
- 創建不同類型的賬戶(儲蓄/支票)
- 存款/取款操作
- 計算利息(僅儲蓄賬戶)
2. 實現步驟
#include <iostream>
#include <vector>
#include <string>
using namespace std;class Account {
protected:string accountNumber;double balance;
public:Account(string accNo, double amt) : accountNumber(accNo), balance(amt) {}virtual void display() const = 0; // 純虛函數
};class SavingsAccount : public Account {
private:double interestRate;
public:SavingsAccount(string accNo, double amt, double rate): Account(accNo, amt), interestRate(rate) {}void deposit(double amt) {balance += amt;}void withdraw(double amt) {if (balance >= amt) {balance -= amt;}}void addInterest() {balance += balance * interestRate / 100;}void display() const override {cout << "儲蓄賬戶(" << accountNumber << "):余額$" << balance << endl;}
};class CheckingAccount : public Account {
public:CheckingAccount(string accNo, double amt): Account(accNo, amt) {}void deposit(double amt) {balance += amt;}bool withdraw(double amt) {if (balance >= amt) {balance -= amt;return true;}return false;}void display() const override {cout << "支票賬戶(" << accountNumber << "):余額$" << balance << endl;}
};int main() {vector<Account*> accounts;// 創建賬戶accounts.push_back(new SavingsAccount("SA123", 5000, 2.5));accounts.push_back(new CheckingAccount("CA456", 2000));// 存款操作accounts[0]->deposit(1000);accounts[1]->deposit(500);// 取款操作accounts[0]->withdraw(200);accounts[1]->withdraw(1500); // 余額不足// 顯示所有賬戶cout << "\n📊 賬戶信息:" << endl;for (const auto& acc : accounts) {acc->display();}// 清理內存for (auto acc : accounts) {delete acc;}return 0;
}
四、🛠? 進階技巧
1. 構造函數初始化列表
class Point {
public:Point(double x, double y) : x(x), y(y) {} // 直接初始化成員變量
private:double x, y;
};
2. 多態實現原理
// 純虛函數聲明
virtual void draw() = 0;// 重寫(override)關鍵字(C++11)
void draw() override;
3. 抽象類與接口
class Shape { // 抽象類
public:virtual void draw() = 0; // 純虛函數
};class Circle : public Shape {
public:void draw() override { /* 繪制圓 */ }
};
五、? 常見問題解答
Q:類和結構體有什么本質區別?
→ 默認訪問權限不同(類private/結構體public),設計意圖不同(類強調封裝/結構體側重數據組織)
Q:什么是虛函數??
→ 用于實現多態機制的成員函數,通過virtual關鍵字聲明
Q:構造函數可以調用虛函數嗎??
→ 不建議,此時虛函數調用的是基類的實現而非派生類
六、📝 今日總結
? 成功掌握:
- 🔑 類的定義與對象創建方法
- 🔒 封裝實現數據隱藏
- 🌟 繼承與多態的基本應用
- 💡 構造函數/析構函數的編寫規范
? 明日預告:
- 模板編程基礎(泛型編程)
七、📝 課后挑戰任務
1.🌟 完善銀行系統:
- 添加賬戶類型判斷功能
- 實現按賬戶類型統計總金額
2. 🔍 抽象類應用:
// 完成圖形面積計算程序
class Shape {
public:virtual double area() = 0;
};class Circle : public Shape {
private:double radius;
public:Circle(double r) : radius(r) {}double area() override { return 3.14 * radius * radius; }
};class Rectangle : public Shape {
private:double width, height;
public:Rectangle(double w, double h) : width(w), height(h) {}double area() override { return width * height; }
};int main() {Shape* shapes[2];shapes[0] = new Circle(5);shapes[1] = new Rectangle(4, 6);cout << "總面積:" << shapes[0]->area() + shapes[1]->area() << endl;// 釋放內存delete[] shapes;return 0;
}
3.📝 技術總結:
- 列舉面向對象編程的5個典型應用場景
🔍 上一天課后挑戰任務答案
任務1:圖書館管理系統擴展(知識點拆解)
📚 核心知識點
-
?結構體擴展?
- 在原有
LibraryBook
結構體中添加borrowerName
和isBorrowed
字段 - 示例代碼:
struct LibraryBook {string isbn;string title;string author;double price;string borrowerName;bool isBorrowed; };
- 在原有
-
?動態數據管理?
- 使用
vector<LibraryBook>
存儲圖書信息 - 添加借閱邏輯:
// 借閱操作 void borrowBook(vector<LibraryBook>& books, const string& isbn, const string& name) {for (auto& book : books) {if (book.isbn == isbn && !book.isBorrowed) {book.borrowerName = name;book.isBorrowed = true;cout << "📖《" << book.title << "》已借出!" << endl;return;}}cout << "📝 該書不可借閱或已被借出!" << endl; }
- 使用
-
?范圍查詢實現?
- 按價格區間篩選圖書:
vector<LibraryBook> filterByPrice(const vector<LibraryBook>& books, double minPrice, double maxPrice) {vector<LibraryBook> result;for (const auto& book : books) {if (book.price >= minPrice && book.price <= maxPrice) {result.push_back(book);}}return result; }
- 按價格區間篩選圖書:
🛠? 實現技巧
- ?數據持久化:使用文件流保存借閱記錄(
fstream
) - ?界面優化:添加菜單循環和輸入驗證
- ?異常處理:處理無效ISBN輸入(
cin.fail()
)
任務2:時間格式轉換程序(深入解析)
🔍 關鍵知識點
-
?聯合體(Union)的特性?
- 所有成員共享同一塊內存地址
- 示例內存布局:
totalSeconds (int) | hours (int) | minutes (int) | seconds (int) ----------------------------------------------- 0x0000 | 0x0004 | 0x0008 | 0x000C
-
?類型轉換方法?
- 通過成員訪問符切換不同視圖:
Time t; t.totalSeconds = 3661; // 初始化為總秒數 cout << "小時:" << t.hours << endl; // 自動轉換顯示
- 通過成員訪問符切換不同視圖:
-
?取模運算原理?
- 計算時分秒的數學公式:
hours = totalSeconds / 3600 remaining = totalSeconds % 3600 minutes = remaining / 60 seconds = remaining % 60
- 計算時分秒的數學公式:
🎯 進階應用
- ?時區轉換:添加時區偏移量參數
- ?閏年判斷:擴展日期計算功能
- ?時間格式化:輸出ISO 8601標準格式(
YYYY-MM-DD HH:MM:SS
)
任務3:技術總結表(知識點擴展)
應用場景 | 結構體設計要點 | 實際開發建議 |
---|---|---|
學生信息管理 | 包含學號/姓名/成績/年級 | 使用std::vector 存儲動態數據 |
幾何圖形計算 | 包含坐標/面積/周長 | 重載運算符(如+ 表示向量相加) |
文件元數據存儲 | 包含創建時間/修改時間/大小 | 使用struct 代替class 提升效率 |
通信協議解析 | 包含版本號/數據長度/校驗和 | 添加序列化(serialization)功能 |
📊 內存對比示意圖
// 結構體內存布局示例
struct Student {int id; // 4 byteschar name[20]; // 20 bytesfloat score; // 4 bytes
};// 聯合體內存布局示例
union Data {int integer; // 4 bytesdouble floating; // 8 byteschar character; // 1 byte
};