实验3

实验任务1:

button.hpp:

#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";
}

window.hpp

#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 {
    // 显示方法实现(图片中未完整显示)
}

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;
}

test.cpp

#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();
}

运行结果:

屏幕截图 2025-11-22 162014

问题1:

是组合关系

问题2:

优点是更加的灵活,缺点是破坏了封装性

问题3:

接口2的安全性比接口1更高,但是性能没有接口一好

问题4:

第一种写法先构造在拷贝,第2种直接在内存空间中构造了button对象

实验任务2:

#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: ";output2(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:\n";output3(v1);
     std::cout<<"v2:\n";output3(v2);
 }
 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';
 }
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';
    }
}
 void output3(const std::vector<std::vector<int>>&v)
 {
     if(v.size()==0)
     {
         std::cout<<'\n';
         return;
     }
     for(auto &i:v)
        output2(i);
 }
 
 
 
 
 
 

实验结果:

屏幕截图 2025-11-22 170053

问题1:

v1包含5个

v2包含5个42的值

问题2:

v1.size()=2

v2.size()=2

v1[0].size()=3

问题3:

at()进行了边界检查更加安全

[]不进行边界检查性能较好

问题4:

1,能输出-1,v1.at()在vector内部第一个使用

2.具有更高的性能,不会产生临时对象

但是不能修改被应用的对象

问题5:

1.深复制

2.int&;vector(int)&;需要提供带const的修饰版本

实验任务3:

 vectorint.hpp:

#pragma once
#include <iostream>
// 动态int数组对象类
class vectorInt {
public:
    vectorInt();
    vectorInt(int n_);
    vectorInt(int n_, int value);
    vectorInt(const vectorInt &v1);
    ~vectorInt();

    int size() const;
    int& at(int index);
    const int& at(int index) const;
    vectorInt& assign(const vectorInt &v1);

    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 (int i = 0; i < n_; ++i)
        ptr[i] = value;
}

vectorInt::vectorInt(const vectorInt &v1) : n(v1.n), ptr(new int[v1.n]) {
    for (int i = 0; i < v1.n; ++i)
        ptr[i] = v1.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 &v1) {
    if (this == &v1)
        return *this;
    int *ptr_tmp = new int[v1.n];
    for (int i = 0; i < v1.n; ++i)
        ptr_tmp[i] = v1.ptr[i];
    delete[] ptr;
    n = v1.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;
}

test.cpp:

#include <iostream>
#include "vectorInt.hpp"
void test1();
void test2();
void output1(const vectorInt &v1);
void output2(const vectorInt &v1);

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);
}

// 使用 at() + 循环输出 vectorInt 对象数据项
void output1(const vectorInt &v1) {
    if (v1.size() == 0) {
        std::cout << "\n";
        return;
    }
    std::cout << v1.at(0);
    for (auto i = 1; i < v1.size(); ++i)
        std::cout << ", " << v1.at(i);
    std::cout << "\n";
}

// 使用迭代器 + 循环输出 vectorInt 对象数据项
void output2(const vectorInt &v1) {
    if (v1.size() == 0) {
        std::cout << "\n";
        return;
    }
    auto it = v1.begin();
    std::cout << *it;
    for (it = v1.begin() + 1; it != v1.end(); ++it)
        std::cout << ", " << *it;
    std::cout << "\n";
}

实验结果:、

屏幕截图 2025-11-23 121740

问题1:

1.缺少自生赋值的检查

2.参数名不一致

3.内存释放后无法被恢复

问题2:

static_cast<const vectorInt*>(this)将this指针从vectorint*转化为const vectorint*,避免了代码的重复

const_cast<int&>移除返回值const限定,匹配非const版本的返回类型

问题3:

非const版本:用于需要修改容器内容的场景

const的版本:用于只读访问保证内容不会修改

迭代器本质是提供访问接口

问题4:

std::fill_n(ptr,n,value) 

将ptr开始的前n个元素都设置为value

手动循环:for(int i=0;i<n;++i)ptr[i]=value;

std::copy_n(v1.ptr,v1.n,ptr)

从v1.ptr复制v1.n个元素到ptr

手动循环:for(int i=0;i<v1.n;++i)ptr[i]=v1.ptr[i];

std::copy_n(v1.ptr,v1.n,ptr_tmp)

复制数据代买更加简洁不易出错

实验任务4:

matrix.hpp

#pragma once

class Matrix {
public:
    Matrix(int rows_, int cols_, double value = 0); 
    Matrix(int rows_, double value = 0);
    Matrix(const Matrix &x); 
    ~Matrix(); 

    void set(const double *pvalue, int size); 
    void clear(); 
    const double& at(int i, int j) const; 
    double& at(int i, int j); 
    int rows() const; 
    int cols() const; 
    void print() const; 

private:
    int n_rows; 
    int n_cols; 
    double *ptr; 
};

matrix.cpp

#include <iostream>
#include <cstdlib>
#include "matrix.hpp"
Matrix::Matrix(int rows_, int cols_, double value) 
    : n_rows(rows_), n_cols(cols_) {
    if (rows_ <= 0 || cols_ <= 0) {
        std::cerr << "Error: Invalid matrix dimensions\n";
        std::exit(1);
    }
    ptr = new double[n_rows * n_cols];
    for (int i = 0; i < n_rows * n_cols; ++i) {
        ptr[i] = value;
    }
}
Matrix::Matrix(int rows_, double value) 
    : n_rows(rows_), n_cols(rows_) {
    if (rows_ <= 0) {
        std::cerr << "Error: Invalid matrix dimensions\n";
        std::exit(1);
    }
    ptr = new double[n_rows * n_cols];
    for (int i = 0; i < n_rows * n_cols; ++i) {
        ptr[i] = value;
    }
}
Matrix::Matrix(const Matrix &x) 
    : n_rows(x.n_rows), n_cols(x.n_cols) {
    ptr = new double[n_rows * n_cols];
    for (int i = 0; i < n_rows * n_cols; ++i) {
        ptr[i] = x.ptr[i];
    }
}
Matrix::~Matrix() {
    delete[] ptr;
}
void Matrix::set(const double *pvalue, int size) {
    if (size != n_rows * n_cols) {
        std::cerr << "Error: Size mismatch in set function\n";
        std::exit(1);
    }
    for (int i = 0; i < size; ++i) {
        ptr[i] = pvalue[i];
    }
}
void Matrix::clear() {
    for (int i = 0; i < n_rows * n_cols; ++i) {
        ptr[i] = 0;
    }
}
const double& Matrix::at(int i, int j) const {
    if (i < 0 || i >= n_rows || j < 0 || j >= n_cols) {
        std::cerr << "Error: Index out of range\n";
        std::exit(1);
    }
    return ptr[i * n_cols + j];
}
double& Matrix::at(int i, int j) {
    if (i < 0 || i >= n_rows || j < 0 || j >= n_cols) {
        std::cerr << "Error: Index out of range\n";
        std::exit(1);
    }
    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);
        for (int j = 1; j < n_cols; ++j) {
            std::cout << ", " << at(i, j);
        }
        std::cout << '\n';
    }
}

task4.cpp

#include <iostream>
#include <cstdlib>
#include "matrix.hpp"

void test1();
void test2();
void output(const Matrix &m, int row_index);

int main() {
    std::cout << "测试1: \n";
    test1();
    std::cout << "\n测试2: \n";
    test2();
}

void test1() {
    double x[1000] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
    int n, m;
    std::cout << "Enter n and m: ";
    std::cin >> n >> m;

    Matrix m1(n, m); 
    m1.set(x, n*m); 
    Matrix m2(m, n); 
    m2.set(x, m*n); 
    Matrix m3(n); 
    m3.set(x, n*n); 

    std::cout << "矩阵对象m1: \n"; m1.print();
    std::cout << "矩阵对象m2: \n"; m2.print();
    std::cout << "矩阵对象m3: \n"; m3.print();
}

void test2() {
    Matrix m1(2, 3, -1);
    const Matrix m2(m1);

    std::cout << "矩阵对象m1: \n"; m1.print();
    std::cout << "矩阵对象m2: \n"; m2.print();

    m1.clear();
    m1.at(0, 0) = 1;

    std::cout << "m1更新后: \n";
    std::cout << "矩阵对象m1第0行: "; output(m1, 0);
    std::cout << "矩阵对象m2第0行: "; output(m2, 0);
}
void output(const Matrix &m, int row_index) {
    if (row_index < 0 || row_index >= m.rows()) {
        std::cerr << "IndexError: row index out of range\n";
        std::exit(1);
    }
    std::cout << m.at(row_index, 0);
    for (int j = 1; j < m.cols(); ++j) {
        std::cout << ", " << m.at(row_index, j);
    }
    std::cout << '\n';
}

实验结果

屏幕截图 2025-11-23 143844

实验任务5:

contact.hpp

#pragma once
#include <iostream>
#include <string>
class Contact {
public:
    Contact(const std::string &name_, const std::string &phone_);
    const std::string &get_name() const;
    const std::string &get_phone() const;
    void display() const;

private:
    std::string name; // 必填项
    std::string phone; // 必填项
};

Contact::Contact(const std::string &name_, const std::string &phone_):name(name_), phone(phone_) {
}

const std::string& Contact::get_name() const {
    return name;
}

const std::string& Contact::get_phone() const {
    return phone;
}

void Contact::display() const {
    std::cout << name << ", " << phone;
}

contactBook.hpp

#pragma once
#include <iostream>
#include <string>
#include <vector>
#include <algorithm>
#include "contact.hpp"
class ContactBook {
publicvoid add(const std::string &name, const std::string &phone); 
    void remove(const std::string &name); 
    void find(const std::string &name) const; 
    void display() const; 
    size_t size() const;

private:
    int index(const std::string &name) const; 
    void sort(); 

private:
    std::vector<Contact> contacts;
};

void ContactBook::add(const std::string &name, const std::string &phone) {
    if(index(name) == -1) {
        contacts.push_back(Contact(name, phone));
        std::cout << name << " add successfully.\n";
        sort();
        return;
    }
    std::cout << name << " already exists. fail to add!\n";
}

void ContactBook::remove(const std::string &name) {
    int i = index(name);
    if(i == -1) {
        std::cout << name << " not found, fail to remove!\n";
        return;
    }
    contacts.erase(contacts.begin() + i);
    std::cout << name << " remove successfully.\n";
}

void ContactBook::find(const std::string &name) const {
    int i = index(name);
    if(i == -1) {
        std::cout << name << " not found!\n";
        return;
    }
    contacts[i].display();
    std::cout << '\n';
}

void ContactBook::display() const {
    for(auto &c: contacts) {
        c.display();
        std::cout << '\n';
    }
}

size_t ContactBook::size() const {
    return contacts.size();
}

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;
}

void ContactBook::sort() {
    std::sort(contacts.begin(), contacts.end(), 
        [](const Contact &a, const Contact &b) {
            return a.get_name() < b.get_name();
        });
}

task5.cpp

#include "contactBook.hpp"
#include <iostream>

void test() {
    ContactBook contactbook;

    std::cout << "1. add contacts\n";
    contactbook.add("Bob", "18199357253");
    contactbook.add("Alice", "17300886371");
    contactbook.add("Linda", "18184538072");
    contactbook.add("Alice", "17300886371");

    std::cout << "\n2. display contacts\n";
    std::cout << "There are " << contactbook.size() << " contacts.\n";
    contactbook.display();

    std::cout << "\n3. find contacts\n";
    contactbook.find("Bob");
    contactbook.find("David");

    std::cout << "\n4. remove contact\n";
    contactbook.remove("Bob");
    contactbook.remove("David");
}

int main() {
    test();
    return 0;
}

实验结果:

屏幕截图 2025-11-23 151519

 

posted @ 2025-11-23 15:17  fuilk  阅读(6)  评论(1)    收藏  举报