实验3
一.

#pragma once #include <iostream> #include <string> class Button { public: Button(const std::string& label_); const std::string& get_label() const; void click(); private: std::string label; }; Button::Button(const std::string& label_) : label{ label_ } { } inline const std::string& Button::get_label() const { return label; } inline void Button::click() { std::cout << "Button '" << label << "' clicked\n"; } #pragma once #include <iostream> #include <vector> #include <algorithm> #include "button.hpp" // 窗口类 class Window { public: Window(const std::string& title_); void display() const; void close(); void add_button(const std::string& label); void click_button(const std::string& label); private: bool has_button(const std::string& label) const; private: std::string title; std::vector<Button> buttons; }; Window::Window(const std::string& title_) : title{ title_ } { buttons.push_back(Button("close")); } inline void Window::display() const { std::string s(40, '*'); std::cout << s << std::endl; std::cout << "window : " << title << std::endl; int cnt = 0; for (const auto& button : buttons) std::cout << ++cnt << ". " << button.get_label() << std::endl; std::cout << s << std::endl; } inline void Window::close() { std::cout << "close window '" << title << "'" << std::endl; click_button("close"); } inline bool Window::has_button(const std::string& label) const { for (const auto& button : buttons) if (button.get_label() == label) return true; return false; } inline void Window::add_button(const std::string& label) { if (has_button(label)) std::cout << "button " << label << " already exists!\n"; else buttons.push_back(Button(label)); } inline void Window::click_button(const std::string& label) { for (auto& button : buttons) if (button.get_label() == label) { button.click(); return; } std::cout << "no button: " << label << std::endl; } #include "window.hpp" #include <iostream> void test() { Window w("Demo"); w.add_button("add"); w.add_button("remove"); w.add_button("modify"); w.add_button("add"); w.display(); w.close(); } int main() { std::cout << "用组合类模拟简单GUI:\n"; test(); }
1.是
2.1优点:has_button可以直接被外部调用,判断是否有相应label并输出结果,增加新的功能
风险: 破坏封装;has_button与add_button相关,不易于维护
2.2public:用户真正需要调用,
private:仅为内部实现,调用会破坏对象状态
3 性能:接口1使用引用,效率高;
安全:接口1使用时和原对象绑定,容易出现问题
4可以;push_back先构造再移动到vector,而emplace_back直接构造,效率高。
二

#include <iostream> #include <vector> void test1(); void test2(); void output1(const std::vector<int>& v); void output2(const std::vector<int>& v); void output3(const std::vector<std::vector<int>>& v); int main() { std::cout << "深复制验证1: 标准库vector<int>\n"; test1(); std::cout << "\n深复制验证2: 标准库vector<int>嵌套使用\n"; test2(); } void test1() { std::vector<int> v1(5, 42); const std::vector<int> v2(v1); std::cout << "**********拷贝构造后**********\n"; std::cout << "v1: "; output1(v1); std::cout << "v2: "; output1(v2); v1.at(0) = -1; std::cout << "**********修改v1[0]后**********\n"; std::cout << "v1: "; output1(v1); std::cout << "v2: "; output1(v2); } void test2() { std::vector<std::vector<int>> v1{ {1, 2, 3}, {4, 5, 6, 7} }; const std::vector<std::vector<int>> v2(v1); std::cout << "**********拷贝构造后**********\n"; std::cout << "v1: "; output3(v1); std::cout << "v2: "; output3(v2); v1.at(0).push_back(-1); std::cout << "**********修改v1[0]后**********\n"; std::cout << "v1: \n"; output3(v1); std::cout << "v2: \n"; output3(v2); } // 使用xx.at()+循环输出vector<int>数据项 void output1(const std::vector<int>& v) { if (v.size() == 0) { std::cout << '\n'; return; } std::cout << v.at(0); for (auto i = 1; i < v.size(); ++i) std::cout << ", " << v.at(i); std::cout << '\n'; } // 使用迭代器+循环输出vector<int>数据项 void output2(const std::vector<int>& v) { if (v.size() == 0) { std::cout << '\n'; return; } auto it = v.begin(); std::cout << *it; for (it = v.begin() + 1; it != v.end(); ++it) std::cout << ", " << *it; std::cout << '\n'; } // 使用auto for分行输出vector<vector<int>>数据项 void output3(const std::vector<std::vector<int>>& v) { if (v.size() == 0) { std::cout << '\n'; return; } for (auto& i : v) output2(i); }
1.填充式构造,5,5
2. 2;2;3
3.能;v1.at(0)会检查索引合法性,更安全,但是效率更低。
4.1可以;v1.at(0).push_back(-1);将-1添加至v1第 0 个子末尾,之后输出-1;
4.2优势:使用引用,提高效率;
限制:无法修改原对象.
5.1 深复制;
5.2 int&;const int&
是,可以让 const 修饰的 vector 也能安全读取元素
三

#pragma once #include <iostream> // 动态int数组对象类 class vectorInt { public: vectorInt(); vectorInt(int n_); vectorInt(int n_, int value); vectorInt(const vectorInt& vi); ~vectorInt(); int size() const; int& at(int index); const int& at(int index) const; vectorInt& assign(const vectorInt& vi); int* begin(); int* end(); const int* begin() const; const int* end() const; private: int n;// 当前数据项个数 int* ptr; // 数据区 }; vectorInt::vectorInt() :n{ 0 }, ptr{ nullptr } { } vectorInt::vectorInt(int n_) : n{ n_ }, ptr{ new int[n] } { } vectorInt::vectorInt(int n_, int value) : n{ n_ }, ptr{ new int[n_] } { for (auto i = 0; i < n; ++i) ptr[i] = value; } vectorInt::vectorInt(const vectorInt& vi) : n{ vi.n }, ptr{ new int[n] } { for (auto i = 0; i < n; ++i) ptr[i] = vi.ptr[i]; } vectorInt::~vectorInt() { delete[] ptr; } int vectorInt::size() const { return n; } const int& vectorInt::at(int index) const { if (index < 0 || index >= n) { std::cerr << "IndexError: index out of range\n"; std::exit(1); } return ptr[index]; } int& vectorInt::at(int index) { if (index < 0 || index >= n) { std::cerr << "IndexError: index out of range\n"; std::exit(1); } return ptr[index]; } vectorInt& vectorInt::assign(const vectorInt& vi) { if (this == &vi) return *this; int* ptr_tmp; ptr_tmp = new int[vi.n]; for (int i = 0; i < vi.n; ++i) ptr_tmp[i] = vi.ptr[i]; delete[] ptr; n = vi.n; ptr = ptr_tmp; return *this; } int* vectorInt::begin() { return ptr; } int* vectorInt::end() { return ptr + n; } const int* vectorInt::begin() const { return ptr; } const int* vectorInt::end() const { return ptr + n; } #include "vectorInt.hpp" #include <iostream> void test1(); void test2(); void output1(const vectorInt& vi); void output2(const vectorInt& vi); int main() { std::cout << "测试1: \n"; test1(); std::cout << "\n测试2: \n"; test2(); } void test1() { int n; std::cout << "Enter n: "; std::cin >> n; vectorInt x1(n); for (auto i = 0; i < n; ++i) x1.at(i) = (i + 1) * 10; std::cout << "x1: "; output1(x1); vectorInt x2(n, 42); vectorInt x3(x2); x2.at(0) = -1; std::cout << "x2: "; output1(x2); std::cout << "x3: "; output1(x3); } void test2() { const vectorInt x(5, 42); vectorInt y; y.assign(x); std::cout << "x: "; output2(x); std::cout << "y: "; output2(y); } // 使用xx.at()+循环输出vectorInt对象数据项 void output1(const vectorInt& vi) { if (vi.size() == 0) { std::cout << '\n'; return; } std::cout << vi.at(0); for (auto i = 1; i < vi.size(); ++i) std::cout << ", " << vi.at(i); std::cout << '\n'; } // 使用迭代器+循环输出vectorInt对象数据项 void output2(const vectorInt& vi) { if (vi.size() == 0) { std::cout << '\n'; return; } auto it = vi.begin(); std::cout << *it; for (it = vi.begin() + 1; it != vi.end(); ++it) std::cout << ", " << *it; std::cout << '\n'; }
1.原代码
if (this == &vi)
return *this;
判断调用对象和传入参数是否相同,防止错误;
释放和分配内存顺序不同,防止内存分配失败
2.1作用:将当前对象的指针 this 转换为 const vectorInt* 类型的指针
前:vectorInt* 后:const vectorInt*
目的:让非 const 版本的 at() 函数能够调用 const 版本的 at() 函数
2.2移除 const 限定符,将 const int& 类型转换为 int& 类型。
前:const int& 后:int&
目的:非 const 版本的 at() 函数需要返回可修改的元素引用(int&)
3. it1:无const it2:有const
有const适用于只读
4.可以。 (1)将从 ptr 开始的连续 n 个 int 类型内存单元,全部赋值为 value
(2)从 vi.ptr 指向的内存开始,复制连续 vi.n 个 int 类型元素,粘贴到 ptr 指向的内存区域。
(3)从 vi.ptr 复制连续 vi.n 个 int 元素到 ptr_tmp 指向的新内存中
四

#include <iostream> #include <cstdlib> #include <algorithm> #include "matrix.hpp" Matrix::Matrix(int rows_, int cols_, double value ) { //补 if (n_rows <= 0 || n_cols <= 0) { std::cerr << "Error: 行数/列数不能为非正数\n"; exit(1); } n_rows = rows_; n_cols = cols_; ptr = new double[n_rows * n_cols]; std::fill(ptr, ptr + n_rows * n_cols, value); } Matrix::Matrix(int rows_, double value ) { n_rows = rows_; n_cols = rows_; ptr = new double[n_rows * n_cols]; std::fill(ptr, ptr + n_rows * n_cols, value); } Matrix::Matrix(const Matrix& x) { n_rows = x.n_rows; n_cols = x.n_cols; ptr = new double[n_rows * n_cols]; std::copy(x.ptr,x.ptr + n_rows * n_cols,ptr); } Matrix::~Matrix() { delete[] ptr; } void Matrix::set(const double* pvalue, int size) { if (size == n_rows * n_cols) { std::copy(pvalue, pvalue + size, ptr); } else { std::cout << "wrong"; exit(1); } } void Matrix::clear() { std::fill(ptr, ptr + n_rows * n_cols,0); } const double& Matrix::at(int i, int j) const { if (i<0||j<0||i>=n_rows||j>=n_cols) {std::cout << "wrong"; exit(1); } else { return ptr[i * n_cols + j]; } } double& Matrix::at(int i, int j) { if (i < 0 || j < 0 || i >= n_rows || j >= n_cols) { std::cout << "wrong"; exit(1); } else { return ptr[i * n_cols + j]; } } int Matrix::rows() const { return n_rows; } int Matrix::cols() const { return n_cols; } void Matrix::print() const { for (int i = 0;i < n_rows;i++) { //std::cout << at(i, 0) << ","; //std::cout << std::endl; for (int j = 0;j < n_cols;j++) std::cout << at(i, j) << ","; std::cout << std::endl;} }
五

int ContactBook::index(const std::string& name) const { for (size_t i=0;i< contacts.size();++i ) { if (contacts[i].get_name()==name) return static_cast<int>(i); } return -1; } // 返回联系人在contacts内索引; 如不存在,返回-1 // 待补足2:void ContactBook::sort();实现 void ContactBook::sort() { size_t n = size(); for (size_t i = 0;i <n;++i) { for (size_t j = 0;j < n - i - i;++j) { if (contacts[j].get_name() > contacts[j + 1].get_name()) { std::swap(contacts[j], contacts[j + 1]); } } } }

浙公网安备 33010602011771号