任務一:

源代碼:

button.hpp

1 #pragma once
 2 
 3 #include <iostream>
 4 #include <string>
 5 
 6 class Button {
 7 public:
 8     Button(const std::string &label_);
 9     const std::string& get_label() const;
10     void click();
11 
12 private:
13     std::string label;
14 };
15 
16 Button::Button(const std::string &label_): label{label_} {
17 }
18 
19 inline const std::string& Button::get_label() const {
20     return label;
21 }
22 
23 inline void Button::click() {
24     std::cout << "Button '" << label << "' clicked\n";
25 }

View Code

 

window.hpp

1 #pragma once
 2 
 3 #include <iostream>
 4 #include <vector>
 5 #include <algorithm>
 6 #include "button.hpp"
 7 
 8 // 窗口類
 9 class Window{
10 public:
11     Window(const std::string &title_);
12     void display() const;
13     void close();
14     void add_button(const std::string &label);
15     void click_button(const std::string &label);
16 
17 private:
18     bool has_button(const std::string &label) const;
19 
20 private:
21     std::string title;
22     std::vector<Button> buttons;
23 };
24 
25 Window::Window(const std::string &title_): title{title_} {
26     buttons.push_back(Button("close"));
27 }
28 
29 inline void Window::display() const {
30     std::string s(40, '*');
31     std::cout << s << std::endl;
32     std::cout << "window : " << title << std::endl;
33     int cnt = 0;
34     for(const auto &button: buttons)
35         std::cout << ++cnt << ". " << button.get_label() << std::endl;
36     std::cout << s << std::endl;
37 }
38 
39 inline void Window::close() {
40     std::cout << "close window '" << title << "'" << std::endl;
41     click_button("close");
42 }
43 
44 inline bool Window::has_button(const std::string &label) const {
45     for(const auto &button: buttons)
46         if(button.get_label() == label)
47             return true;
48     
49     return false;
50 }
51 
52 inline void Window::add_button(const std::string &label) {
53     if(has_button(label))
54         std::cout << "button " << label << " already exists!\n";
55     else
56         buttons.push_back(Button(label));
57 }
58 
59 inline void Window::click_button(const std::string &label) {
60     for(auto &button:buttons)
61         if(button.get_label() == label) {
62             button.click();
63             return;
64         }
65             
66     std::cout << "no button: " << label << std::endl;
67 }

View Code

 

task1.cpp

1 #include "window.hpp"
 2 #include <iostream>
 3 
 4 void test(){
 5     Window w("Demo");
 6     w.add_button("add");
 7     w.add_button("remove");
 8     w.add_button("modify");
 9     w.add_button("add");
10     w.display();
11     w.close();
12 }
13 
14 int main() {
15     std::cout << "用組合類模擬簡單GUI:\n";
16     test();
17 }

View Code

 運行結果:


 

問題1:是,Button存在於Window的buttons向量中

問題2:(1)優點:增強接口的完整性和可用性,支持更靈活的使用場景;缺點:暴露內部實現細節,破壞封裝性,增加維護成本

          (2)用户需求:用户完成主要任務需要直接調用的核心功能應設為 public;僅為內部服務,用户不需要直接調用應設為 private

              實現細節:提供穩定的抽象接口應設為 public;涉及具體的算法、數據結構等實現細節應設為 private

              狀態安全:保證操作後對象狀態依然完整、有效可設為 public;可能破壞對象狀態一致性或不變式時設為 private

問題3:接口1:性能高效,返回引用避免拷貝;安全性較低,調用者可能持有失效的引用(如Button對象被銷燬後)

          接口2:性能較低,涉及字符串拷貝;安全性較高,返回副本不會受原對象生命週期影響

問題4:正常運行

push_back(Button(label)):先構造臨時Button對象,再拷貝或移動到容器中,涉及兩次構造(臨時對象+容器內對象)

emplace_back(label):直接在容器內存中構造Button對象,只涉及一次構造,更高效,避免不必要的拷貝/移動

 

任務二:

源代碼:

task2.cpp

1 #include <iostream>
 2 #include <vector>
 3 
 4 void test1();
 5 void test2();
 6 void output1(const std::vector<int> &v);
 7 void output2(const std::vector<int> &v);
 8 void output3(const std::vector<std::vector<int>>& v);
 9 
10 int main() {
11     std::cout << "深複製驗證1: 標準庫vector<int>\n";
12     test1();
13 
14     std::cout << "\n深複製驗證2: 標準庫vector<int>嵌套使用\n";
15     test2();
16 }
17 
18 void test1() {
19     std::vector<int> v1(5, 42);
20     const std::vector<int> v2(v1);
21 
22     std::cout << "**********拷貝構造後**********\n";
23     std::cout << "v1: "; output1(v1);
24     std::cout << "v2: "; output1(v2);
25     
26     v1.at(0) = -1;
27 
28     std::cout << "**********修改v1[0]後**********\n";
29     std::cout << "v1: "; output1(v1);
30     std::cout << "v2: "; output1(v2); 
31 }
32 
33 void test2() {
34     std::vector<std::vector<int>> v1{{1, 2, 3}, {4, 5, 6, 7}};
35     const std::vector<std::vector<int>> v2(v1);
36 
37     std::cout << "**********拷貝構造後**********\n";
38     std::cout << "v1: "; output3(v1);
39     std::cout << "v2: "; output3(v2);
40 
41     v1.at(0).push_back(-1);
42 
43     std::cout << "**********修改v1[0]後**********\n";
44     std::cout << "v1: \n";  output3(v1);
45     std::cout << "v2: \n";  output3(v2);
46 }
47 
48 // 使用xx.at()+循環輸出vector<int>數據項
49 void output1(const std::vector<int> &v) {
50     if(v.size() == 0) {
51         std::cout << '\n';
52         return;
53     }
54     
55     std::cout << v.at(0);
56     for(auto i = 1; i < v.size(); ++i)
57         std::cout << ", " << v.at(i);
58     std::cout << '\n';  
59 }
60 
61 // 使用迭代器+循環輸出vector<int>數據項
62 void output2(const std::vector<int> &v) {
63     if(v.size() == 0) {
64         std::cout << '\n';
65         return;
66     }
67     
68     auto it = v.begin();
69     std::cout << *it;
70 
71     for(it = v.begin()+1; it != v.end(); ++it)
72         std::cout << ", " << *it;
73     std::cout << '\n';
74 }
75 
76 // 使用auto for分行輸出vector<vector<int>>數據項
77 void output3(const std::vector<std::vector<int>>& v) {
78     if(v.size() == 0) {
79         std::cout << '\n';
80         return;
81     }
82 
83     for(auto &i: v)
84         output2(i);
85 }

View Code

運行結果:


問題1:

第一行使用構造函數創建;第二行使用拷貝構造函數從v1創建v2

v1、v2各包含5個值為42的數據項

問題2:

v1.size()=2 

v2.size()=2   

v3.size()=3

問題3:能實現同等效果

at()會進行邊界檢查,如果索引越界會拋出std::_out of range異常,更安全但性能稍差;

[ ]不進行邊界檢查,越界時行為未定義,可能崩潰或產生不可預料結果

問題4:

(1)能,  v1.at(0)返回第一個內層vector的引用;push_back(-1)在該vector末尾添加了-1

(2)優勢:避免拷貝整個vector,節省內存和時間;

    限制:不能通過r修改vector的內容(因為是const引用)

問題5:

(1)深複製

(2) 當v是vector<int> 時,v.at(0)返回int&

當v是const vector<int>時,v.at(0)返回const int&

at()必須提供const修飾的重載版本,因為對於const對象,需要返回const引用以保證不會意外修改

 

任務3:

源代碼:

vectorInt.hpp

1 #pragma once
  2 
  3 #include <iostream>
  4 
  5 // 動態int數組對象類
  6 class vectorInt{
  7 public:
  8     vectorInt();
  9     vectorInt(int n_);
 10     vectorInt(int n_, int value);
 11     vectorInt(const vectorInt &vi);
 12     ~vectorInt();
 13     
 14     int size() const;
 15     int& at(int index);
 16     const int& at(int index) const;
 17     vectorInt& assign(const vectorInt &vi);
 18 
 19     int* begin();
 20     int* end();
 21     const int* begin() const;
 22     const int* end() const;
 23 
 24 private:
 25     int n;     // 當前數據項個數
 26     int *ptr;  // 數據區
 27 };
 28 
 29 vectorInt::vectorInt():n{0}, ptr{nullptr} {
 30 }
 31 
 32 vectorInt::vectorInt(int n_): n{n_}, ptr{new int[n]} {
 33 }
 34 
 35 vectorInt::vectorInt(int n_, int value): n{n_}, ptr{new int[n_]} {
 36     for(auto i = 0; i < n; ++i)
 37         ptr[i] = value;
 38 }
 39 
 40 vectorInt::vectorInt(const vectorInt &vi): n{vi.n}, ptr{new int[n]} {
 41     for(auto i = 0; i < n; ++i)
 42         ptr[i] = vi.ptr[i];
 43 }
 44 
 45 vectorInt::~vectorInt() {
 46     delete [] ptr;
 47 }
 48 
 49 int vectorInt::size() const {
 50     return n;
 51 }
 52 
 53 const int& vectorInt::at(int index) const {
 54     if(index < 0 || index >= n) {
 55         std::cerr << "IndexError: index out of range\n";
 56         std::exit(1);
 57     }
 58 
 59     return ptr[index];
 60 }
 61 
 62 int& vectorInt::at(int index) {
 63     if(index < 0 || index >= n) {
 64         std::cerr << "IndexError: index out of range\n";
 65         std::exit(1);
 66     }
 67 
 68     return ptr[index];
 69 }
 70 
 71 vectorInt& vectorInt::assign(const vectorInt &vi) { 
 72     if(this == &vi) 
 73         return *this;
 74 
 75     int *ptr_tmp;
 76     ptr_tmp = new int[vi.n];
 77     for(int i = 0; i < vi.n; ++i)
 78         ptr_tmp[i] = vi.ptr[i];
 79     
 80     delete[] ptr;
 81     n = vi.n;
 82     ptr = ptr_tmp;
 83     return *this;
 84 }
 85 
 86 int* vectorInt::begin() {
 87     return ptr;
 88 }
 89 
 90 int* vectorInt::end() {
 91     return ptr+n;
 92 }
 93 
 94 const int* vectorInt::begin() const {
 95     return ptr;
 96 }
 97 
 98 const int* vectorInt::end() const {
 99     return ptr+n;
100 }

View Code

task3.cpp

1 #include <iostream>
 2 #include <vector>
 3 
 4 void test1();
 5 void test2();
 6 void output1(const std::vector<int> &v);
 7 void output2(const std::vector<int> &v);
 8 void output3(const std::vector<std::vector<int>>& v);
 9 
10 int main() {
11     std::cout << "深複製驗證1: 標準庫vector<int>\n";
12     test1();
13 
14     std::cout << "\n深複製驗證2: 標準庫vector<int>嵌套使用\n";
15     test2();
16 }
17 
18 void test1() {
19     std::vector<int> v1(5, 42);
20     const std::vector<int> v2(v1);
21 
22     std::cout << "**********拷貝構造後**********\n";
23     std::cout << "v1: "; output1(v1);
24     std::cout << "v2: "; output1(v2);
25     
26     v1.at(0) = -1;
27 
28     std::cout << "**********修改v1[0]後**********\n";
29     std::cout << "v1: "; output1(v1);
30     std::cout << "v2: "; output1(v2); 
31 }
32 
33 void test2() {
34     std::vector<std::vector<int>> v1{{1, 2, 3}, {4, 5, 6, 7}};
35     const std::vector<std::vector<int>> v2(v1);
36 
37     std::cout << "**********拷貝構造後**********\n";
38     std::cout << "v1: "; output3(v1);
39     std::cout << "v2: "; output3(v2);
40 
41     v1.at(0).push_back(-1);
42 
43     std::cout << "**********修改v1[0]後**********\n";
44     std::cout << "v1: \n";  output3(v1);
45     std::cout << "v2: \n";  output3(v2);
46 }
47 
48 // 使用xx.at()+循環輸出vector<int>數據項
49 void output1(const std::vector<int> &v) {
50     if(v.size() == 0) {
51         std::cout << '\n';
52         return;
53     }
54     
55     std::cout << v.at(0);
56     for(auto i = 1; i < v.size(); ++i)
57         std::cout << ", " << v.at(i);
58     std::cout << '\n';  
59 }
60 
61 // 使用迭代器+循環輸出vector<int>數據項
62 void output2(const std::vector<int> &v) {
63     if(v.size() == 0) {
64         std::cout << '\n';
65         return;
66     }
67     
68     auto it = v.begin();
69     std::cout << *it;
70 
71     for(it = v.begin()+1; it != v.end(); ++it)
72         std::cout << ", " << *it;
73     std::cout << '\n';
74 }
75 
76 // 使用auto for分行輸出vector<vector<int>>數據項
77 void output3(const std::vector<std::vector<int>>& v) {
78     if(v.size() == 0) {
79         std::cout << '\n';
80         return;
81     }
82 
83     for(auto &i: v)
84         output2(i);
85 }

View Code

運行結果:


問題1:

存在的安全隱患和缺陷:

(1)自賦值問題:沒有檢查 this == &vi,如果執行 x.assign(x),第一句 delete[] ptr 會釋放自己的內存,後續訪問 vi.ptr[i] 將訪問已釋放的內存,導致未定義行為。

(2)異常安全問題:new int[n] 可能因內存不足拋出 std::bad_alloc 異常。如果拋出異常,對象將處於無效狀態(ptr 已被刪除但 n 未更新)

(3)內存分配失敗後的狀態不一致:如果 new 失敗,對象將失去原有數據(ptr 已刪除)且無法獲得新數據,處於不可用狀態。

問題2:

(1)static_cast<const vectorInt*>(this) 的作用是執行靜態類型轉換,將當前對象的指針從非常量類型轉換為常量類型。

轉換前的this類型:vectorInt*(指向非常量對象的指針)
轉換後的類型:const vectorInt*(指向常量對象的指針)

轉換目的:將當前對象轉換為常量版本,以便調用const重載的at函數,避免遞歸調用。

(2)const_cast<int&> 的作用是執行常量性轉換,移除返回值的const限定符。

轉換前的返回類型:const int&(從const版本的at返回)
轉換後的返回類型:int&(非常量引用)

轉換目的:移除const限定符,使返回值類型符合非const版本的函數簽名要求。

問題3:

(1)auto it1 = v1.begin()調用非const版本,適配非常量對象,允許通過迭代器修改元素

auto it2 = v2.begin()調用const版本,適配常量對象,只允許讀取,不允許修改

(2)理解:

迭代器本質上是提供了一種統一的元素訪問接口,無論底層是原始指針還是複雜的類對象。vectorInt使用原始指針作為迭代器,説明迭代器是抽象概念,不限於特定實現,只要類型滿足迭代器的基本要求(可遞增、解引用等),就可以作為迭代器使用

問題4:可以

(1)std::fill_n(ptr, n, value);

功能:將 ptr 開始的 n 個元素都設置為 value

(2)std::copy_n(vi.ptr, vi.n, ptr);

功能:從 vi.ptr 精確拷貝 vi.n 個元素到 ptr

(3)std::copy_n(vi.ptr, vi.n, ptr_tmp);

功能:從 vi.ptr 精確拷貝 vi.n 個元素到臨時緩衝區 ptr_tmp

 

任務4:

源代碼:

matrix.hpp

1 #pragma once
 2 
 3 #include <iostream>
 4 #include <algorithm>
 5 #include <cstdlib>
 6 
 7 // 類Matrix聲明
 8 class Matrix {
 9 public:
10     Matrix(int rows_, int cols_, double value = 0); // 構造rows_*cols_矩陣對象, 初值value
11     Matrix(int rows_, double value = 0);    // 構造rows_*rows_方陣對象, 初值value
12     Matrix(const Matrix &x);    // 深複製
13     ~Matrix();
14 
15     void set(const double *pvalue, int size);   // 按行復制pvalue指向的數據,要求size=rows*cols,否則報錯退出
16     void clear();   // 矩陣對象數據項置0
17     
18     const double& at(int i, int j) const;   // 返回矩陣對象索引(i,j)對應的數據項const引用(越界則報錯後退出)
19     double& at(int i, int j);   // 返回矩陣對象索引(i,j)對應的數據項引用(越界則報錯後退出)
20     
21     int rows() const;   // 返回矩陣對象行數
22     int cols() const;   // 返回矩陣對象列數
23 
24     void print() const;   // 按行打印數據
25 
26 private:
27     int n_rows;      // 矩陣對象內元素行數
28     int n_cols;       // 矩陣對象內元素列數
29     double *ptr;    // 數據區
30 };

View Code

matrix.cpp

1 #include "matrix.hpp"
 2 
 3 Matrix::Matrix(int rows_, int cols_, double value) 
 4     : n_rows(rows_), n_cols(cols_), ptr(new double[rows_ * cols_]) {
 5     std::fill_n(ptr, n_rows * n_cols, value);
 6 }
 7 
 8 Matrix::Matrix(int rows_, double value) 
 9     : n_rows(rows_), n_cols(rows_), ptr(new double[rows_ * rows_]) {
10     std::fill_n(ptr, n_rows * n_cols, value);
11 }
12 
13 Matrix::Matrix(const Matrix &x) 
14     : n_rows(x.n_rows), n_cols(x.n_cols), ptr(new double[x.n_rows * x.n_cols]) {
15     std::copy(x.ptr, x.ptr + n_rows * n_cols, ptr);
16 }
17 
18 Matrix::~Matrix() {
19     delete[] ptr;
20 }
21 
22 void Matrix::set(const double *pvalue, int size) {
23     if(size != n_rows * n_cols) {
24         std::cerr << "Error: size mismatch\n";
25         exit(1);
26     }
27     std::copy(pvalue, pvalue + size, ptr);
28 }
29 
30 void Matrix::clear() {
31     std::fill_n(ptr, n_rows * n_cols, 0.0);
32 }
33 
34 const double& Matrix::at(int i, int j) const {
35     if(i < 0 || i >= n_rows || j < 0 || j >= n_cols) {
36         std::cerr << "Error: index out of range\n";
37         exit(1);
38     }
39     return ptr[i * n_cols + j];
40 }
41 
42 double& Matrix::at(int i, int j) {
43     if(i < 0 || i >= n_rows || j < 0 || j >= n_cols) {
44         std::cerr << "Error: index out of range\n";
45         exit(1);
46     }
47     return ptr[i * n_cols + j];
48 }
49 
50 int Matrix::rows() const {
51     return n_rows;
52 }
53 
54 int Matrix::cols() const {
55     return n_cols;
56 }
57 
58 void Matrix::print() const {
59     for(int i = 0; i < n_rows; i++) {
60         std::cout << at(i, 0);
61         for(int j = 1; j < n_cols; j++)
62             std::cout << ", " << at(i, j);
63         std::cout << '\n';
64     }
65 }

View Code

task4.cpp

1 #include <iostream>
 2 #include <cstdlib>
 3 #include "matrix.hpp"
 4 
 5 void test1();
 6 void test2();
 7 void output(const Matrix &m, int row_index);
 8 
 9 int main() {
10     std::cout << "測試1: \n";
11     test1();
12 
13     std::cout << "\n測試2: \n";
14     test2();
15 }
16 
17 void test1() {
18     double x[1000] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
19 
20     int n, m;
21     std::cout << "Enter n and m: ";
22     std::cin >> n >> m;
23 
24     Matrix m1(n, m);    // 創建矩陣對象m1, 大小n×m
25     m1.set(x, n*m);     // 用一維數組x的值按行為矩陣m1賦值
26 
27     Matrix m2(m, n);    // 創建矩陣對象m2, 大小m×n
28     m2.set(x, m*n);     // 用一維數組x的值按行為矩陣m1賦值
29 
30     Matrix m3(n);       // 創建一個n×n方陣對象
31     m3.set(x, n*n);     // 用一維數組x的值按行為矩陣m3賦值
32 
33     std::cout << "矩陣對象m1: \n";   m1.print();
34     std::cout << "矩陣對象m2: \n";   m2.print();
35     std::cout << "矩陣對象m3: \n";   m3.print();
36 }
37 
38 void test2() {
39     Matrix m1(2, 3, -1);
40     const Matrix m2(m1);
41     
42     std::cout << "矩陣對象m1: \n";   m1.print();
43     std::cout << "矩陣對象m2: \n";   m2.print();
44 
45     m1.clear();
46     m1.at(0, 0) = 1;
47 
48     std::cout << "m1更新後: \n";
49     std::cout << "矩陣對象m1第0行 "; output(m1, 0);
50     std::cout << "矩陣對象m2第0行: "; output(m2, 0);
51 }
52 
53 // 輸出矩陣對象row_index行所有元素
54 void output(const Matrix &m, int row_index) {
55     if(row_index < 0 || row_index >= m.rows()) {
56         std::cerr << "IndexError: row index out of range\n";
57         exit(1);
58     }
59 
60     std::cout << m.at(row_index, 0);
61     for(int j = 1; j < m.cols(); ++j)
62         std::cout << ", " << m.at(row_index, j);
63     std::cout << '\n';
64 }

View Code

 運行結果:


任務5:

源代碼:

contact.hpp

1 #pragma once
 2 
 3 #include <iostream>
 4 #include <string>
 5 
 6 // 聯繫人類
 7 class Contact {
 8 public:
 9     Contact(const std::string &name_, const std::string &phone_);
10 
11     const std::string &get_name() const;
12     const std::string &get_phone() const;
13     void display() const;
14 
15 private:
16    std::string name;    // 必填項
17    std::string phone;   // 必填項
18 };
19 
20 Contact::Contact(const std::string &name_, const std::string &phone_):name{name_}, phone{phone_} {
21 }
22 
23 const std::string& Contact::get_name() const {
24     return name;
25 }
26 
27 const std::string& Contact::get_phone() const {
28     return phone;
29 }
30 
31 void Contact::display() const {
32     std::cout << name << ", " << phone;
33 }

View Code

contactBook.hpp

1 # pragma  once
 2 
 3 #include <iostream>
 4 #include <string>
 5 #include <vector>
 6 #include <algorithm>
 7 #include "contact.hpp"
 8 
 9 // 通訊錄類
10 class ContactBook {
11 public:
12     void add(const std::string &name, const std::string &phone); // 添加聯繫人
13     void remove(const std::string &name); // 移除聯繫人
14     void find(const std::string &name) const; // 查找聯繫人
15     void display() const; // 顯示所有聯繫人
16     size_t size() const;
17     
18 private:
19     int index(const std::string &name) const;  // 返回聯繫人在contacts內索引,如不存在,返回-1
20     void sort(); // 按姓名字典序升序排序通訊錄
21 
22 private:
23     std::vector<Contact> contacts;
24 };
25 
26 void ContactBook::add(const std::string &name, const std::string &phone) {
27     if(index(name) == -1) {
28         contacts.push_back(Contact(name, phone));
29         std::cout << name << " add successfully.\n";
30         sort();
31         return;
32     }
33 
34     std::cout << name << " already exists. fail to add!\n"; 
35 }
36 
37 void ContactBook::remove(const std::string &name) {
38     int i = index(name);
39 
40     if(i == -1) {
41         std::cout << name << " not found, fail to remove!\n";
42         return;
43     }
44 
45     contacts.erase(contacts.begin()+i);
46     std::cout << name << " remove successfully.\n";
47 }
48 
49 void ContactBook::find(const std::string &name) const {
50     int i = index(name);
51 
52     if(i == -1) {
53         std::cout << name << " not found!\n";
54         return;
55     }
56 
57     contacts[i].display(); 
58     std::cout << '\n';
59 }
60 
61 void ContactBook::display() const {
62     for(auto &c: contacts) {
63         c.display(); 
64         std::cout << '\n';
65     }
66 }
67 
68 size_t ContactBook::size() const {
69     return contacts.size();
70 }
71 
72 // 待補足1:int index(const std::string &name) const;實現
73 // 返回聯繫人在contacts內索引; 如不存在,返回-1
74 int ContactBook::index(const std::string &name) const {
75     for (size_t i = 0; i < contacts.size(); ++i) {
76         if (contacts[i].get_name() == name) {
77             return static_cast<int>(i);
78         }
79     }
80     return -1;
81 }
82 
83 
84 
85 // 待補足2:void ContactBook::sort();實現
86 // 按姓名字典序升序排序通訊錄
87 void ContactBook::sort() {
88     std::sort(contacts.begin(), contacts.end(),
89         [](const Contact &a, const Contact &b) {
90             return a.get_name() < b.get_name();
91         });
92 }

View Code

task5.cpp

1 #include "contactBook.hpp"
 2 
 3 void test() {
 4     ContactBook contactbook;
 5 
 6     std::cout << "1. add contacts\n";
 7     contactbook.add("Bob", "18199357253");
 8     contactbook.add("Alice", "17300886371");
 9     contactbook.add("Linda", "18184538072");
10     contactbook.add("Alice", "17300886371");
11 
12     std::cout << "\n2. display contacts\n";
13     std::cout << "There are " << contactbook.size() << " contacts.\n";
14     contactbook.display();
15 
16     std::cout << "\n3. find contacts\n";
17     contactbook.find("Bob");
18     contactbook.find("David");
19 
20     std::cout << "\n4. remove contact\n";
21     contactbook.remove("Bob");
22     contactbook.remove("David");
23 }
24 
25 int main() {
26     test();
27 }

View Code

運行結果:


思考:

修改聯繫人:在ContactBook中添加modify(name, new_phone)接口

數據校驗:在Contact構造函數中加入手機號格式驗證

分組管理:為Contact添加group字段,ContactBook支持按組篩選

模糊檢索:擴展find()支持部分姓名匹配,使用std::string::find

保持現有公有接口不變,新增功能通過擴展接口實現,通過組合而非繼承來增強功能

 

總結:

1. 資源管理的深刻理解
通過vectorInt和Matrix類的實現,真正理解了RAII原則和深拷貝的重要性。特別是Matrix類中二維數據的一維化存儲,讓我認識到內存佈局對性能的影響。

2. 封裝與接口設計的平衡
在ContactBook設計中,體會到私有工具函數(index、sort)的價值——既隱藏實現細節,又為公有方法提供支撐。has_button私有化的討論讓我明白:不是所有查詢都需要暴露給用户。

3. 標準庫的高效應用
從手寫循環到std::copy、std::sort的轉變,感受到標準庫算法在簡潔性、安全性和性能上的優勢。

4.const正確性的精妙

at()函數的const重載版本設計,體現了C++對類型安全的嚴格追求。static_cast和const_cast的配合使用展示了類型轉換的藝術。