任務一:
源代碼:
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的配合使用展示了類型轉換的藝術。