Member 類別,包含姓名 (string) 與年齡 (int),兩者皆為常數 (const)。cout << member 輸出格式:姓名 年齡;若年齡為 0 則顯示 ???。MemberList 類別,建構子接受 Member* 與長度,支援 list[name] 透過姓名查詢年齡。#include
#include
#include
#include
using namespace std;
// ==================== Member 類別 ====================
class Member {
const string name; // 常數成員
const int age; // 常數成員
public:
// 預設建構子:產生 "???" 隊員
Member() : name(""), age(0) {}
// 參數建構子
Member(const string& n, int a) : name(n), age(a) {}
// 輸出運算子多載 (友元函數)
friend ostream& operator<<(ostream& os, const Member& m) {
if (m.age == 0) {
os << "???";
} else {
os << m.name << " " << m.age;
}
return os;
}
// 提供查詢介面給 MemberList 使用
const string& GetName() const { return name; }
int GetAge() const { return age; }
};
// ==================== MemberList 類別 ====================
class MemberList {
vector members; // 使用 vector 管理動態陣列
public:
// 建構子:從 Member 陣列複製
MemberList(const Member* arr, int count) {
for (int i = 0; i < count; ++i) {
members.push_back(arr[i]);
}
}
// 索引器:透過姓名查詢年齡
int operator[](const string& name) const {
for (const auto& m : members) {
if (m.GetName() == name) {
return m.GetAge();
}
}
throw out_of_range("Member not found: " + name);
}
};
// ==================== 主程式 ====================
int main() {
// 建立 5 個隊員 (第 5 個使用預設建構子)
Member newCommers[5] = {
Member("Zhang San", 22),
Member("Li Si", 19),
Member("Wang Wu", 18),
Member("Zhao Liu", 24)
// 第 5 個自動為 Member() -> "???"
};
// 輸出所有隊員
cout << "=== 隊員名單 ===" << endl;
for (int i = 0; i < 5; ++i) {
cout << newCommers[i] << endl;
}
// 建立查詢清單
MemberList list(newCommers, 5);
string names[5] = {"Zhang San", "Li Si", "Wang Wu", "Zhao Liu", "Pin Yin"};
cout << "\n=== 年齡查詢 ===" << endl;
for (int i = 0; i < 5; ++i) {
try {
int age = list[names[i]];
cout << names[i] << " : " << age << endl;
} catch (const out_of_range& e) {
cout << names[i] << " : Not Found" << endl;
}
}
return 0;
}
=== 隊員名單 ===
Zhang San 22
Li Si 19
Wang Wu 18
Zhao Liu 24
???
=== 年齡查詢 ===
Zhang San : 22
Li Si : 19
Wang Wu : 18
Zhao Liu : 24
Pin Yin : Not Found
const 成員必須在建構子初始化列表中初始化,無法在建構子本體內指派:
Member(const string& n, int a) : name(n), age(a) {} // ✅ 正確
// Member(const string& n, int a) { name = n; age = a; } // ❌ 編譯錯誤
friend 以存取 private const 成員。const Member& 避免複製,回傳 ostream& 支援串接。???,否則 姓名 年齡。new/delete。const Member* 與計數,相容題目要求的介面。operator[] 回傳 int (年齡),找不到拋出例外 (或可改回傳 -1/optional)。查詢不存在姓名時拋出 std::out_of_range,主程式捕獲並顯示 Not Found,符合題目「查詢 5 個名稱」的需求 (第 5 個 Pin Yin 不存在)。
std::unordered_map 將查詢複雜度從 O(n) 降為 O(1)。std::optional (C++17) 避免例外開銷:optional operator[](const string&) const 。| 錯誤 | 原因 | 修正 |
|---|---|---|
| const 成員未在初始化列表初始化 | C++ 規定 const 成員只能在初始化列表設值 | 使用 Member() : name(""), age(0) {} |
| operator<< 非友元無法存取 private | private 成員外部不可存取 | 加 friend 宣告或提供 public getter |
| MemberList 建構子未複製資料 | 直接存指標導致懸空指標 | 用 vector 深度複製或 shared_ptr |
| 查詢不存在姓名未處理 | 題目要求查詢 5 個名稱含 1 個不存在 | 拋出例外或回傳特殊值 |