实验三类和对象

news/2025/11/25 23:10:31/文章来源:https://www.cnblogs.com/hupo-/p/19240824

实验任务一:

问题1:

  答:是组合关系,Button对象是WIndow对象的组成部分。

问题2:

  答:(1)优点:用户可以调用函数判断窗口中是否有某按钮,帮助用户了解窗口。

  缺点:接口变大了,用户可能会使用has_button接口自己去实现一些判断,但是如果后续类的设计出现其他改动可能会导致用户的逻辑无法实现原有功能,而将has_button设计成private不给用户访问,使得接口最小化,可以在今后的改动中最大限度的使得只改动类的内部而不影响原有代码的功能。

  (2)在设计时我们始终秉持一个原则,在满足用户需要的前提下,尽可能使得接口尽量的小,是封装性发更强,拓展性更强。比如,如果用户确实需要的,设计成public,如果只在类的内部使用用户完全不需要使用的,就设计成private。

问题3:

  答:接口一返回string对象的常引用相较接口儿避免调用复制构造函数,节省不必要的开销,同时,因为避免了复制构造函数的调用,也就避免了深浅复制处理不当导致的安全性问题。

问题四:

  答:能正常运行。xx.push_back(Button(xxx))是调用构造函数生成临时对象作为实参去调用函数,期间总共调用了构造函数和复制构造函两个函数,而xx.emplace_back(xxx)直接在 vector 末尾的内存空间中原地构造元素,仅需传入构造函数的参数,无需临时对象,避免了不必要的额外开销。

 

 

image

 实验任务三:

问题1:

  答:v1是数据元素的int型的动态数组,v2是数据元素是数据元素是int型的vector的动态数组,即v2的每个元素都是一个vector<int>。v1有1个,v2有0个。

问题2:

  答:v1.size() = 2 ;v2.size() = 1 ;v1[0].size() = 3。

问题3:

  答:能实现相同效果。使用xx.at()函数会检查边界,若请求访问的下标越界则会报错,而使用[]访问即使下标越界了也会正常访问。

问题4:

  答:(1)能输出-1. 因为v1是vector<vector<int>>类的对象,它的0号元素就是vector<int>类型的对象,当然可以给vector<int> &类型的变量初始化。

    (2)节省内存,只需要开辟一个小内存存储引用变量,而不需要开领大空间存储完整对象。限制就是引用和原对象会操作同一片内存空间,数据只有一份。

问题5:

  答:(1)深复制。

    (2)返回vint &; 返回const int &;需要。C++ 中,const 对象只能调用 const 成员函数。如果 at() 没有提供 const 重载版本,那么 const vector<int> 类型的对象 v 就无法调用 at() 接口。

实验任务3:

  答:(1)版本2没有自复制处理,若出现自复制,版本二上来直接就把自己的ptr删除了,后续直接全部出错。

     (2)版本2是先删后建,再分配内存成功之前就先删除了原有内存,万一内存分配出错,则会导致原有数据丢失,对象就出现异常了。

问题2:

  答:(1) static_cast<const vectorInt *>(this)作用是将this指针类型转换成cosnt vectorInt*类型;this转换前类型是vectorInt *类型,转换后是 const vectorInt *类型,转换成const类型用来调用常函数版本的at函数。

    (2)const_cast<int&>将const int&转换成int &类型;

转换前是const int & ,转换后是 int&;因为这个版本的at函数要求返回int&类型。

问题3:

  auto it1 = v1.begin();  调用非const版本。

  auto it2 = v2.begin(); 调用const版本。 

问题4:

  答:可行。

  std::fill_n(ptr, n, value);  功能:ptr地址起n个单位的内存赋值成value。

  std::copy_n(vi.ptr, vi.n, ptr); 功能:将[ptr ,ptr+n)区间的值复制到ptr为起点的连续空间。

实验任务四:

 

 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 };
matrix.hpp

 

 1 #include"matrix.hpp"
 2 #include<iostream>
 3 #include<stdlib.h>
 4 Matrix::Matrix(int rows_, int cols_, double value)
 5 {
 6     n_rows = rows_;
 7     n_cols = cols_;
 8     ptr = new double[rows_ * cols_];
 9     for (int i = 0; i < rows_ * cols_; i++)
10         *(ptr + i) = value;
11 }
12 Matrix::Matrix(int rows_ ,double value)
13 {
14     n_rows = rows_;
15     n_cols = rows_;
16     ptr = new double[rows_ * rows_];
17     for (int i = 0; i < rows_ * rows_; i++)
18         *(ptr + i) = value;
19 }
20 Matrix::Matrix(const Matrix& x)
21 {
22     n_rows = x.n_rows;
23     n_cols = x.n_cols;
24     ptr = new double[n_cols * n_rows];
25     for (int i = 0; i < n_cols * n_rows; i++)
26         *(ptr + i) = *(x.ptr + i);
27 }
28 Matrix::~Matrix()
29 {
30     delete[]ptr;
31 }
32 void Matrix::set(const double* pvalue, int size)
33 {
34     if (size != n_cols * n_rows)
35         exit(0);
36     else
37     {
38         for (int i = 0; i < size; i++)
39             *(ptr + i) = *(pvalue + i);
40     }
41 }
42 void Matrix::clear()
43 {
44     for (int i = 0; i < n_rows * n_cols; i++)
45         *(ptr + i) = 0;
46 }
47 const double& Matrix::at(int i, int j) const
48 {
49     int pos = i * n_cols + j;
50     if (pos < 0 || pos >= n_cols * n_rows)
51     {
52         std::cout << "越界访问!\n";
53         exit(0);
54     }
55     else
56         return *(ptr + pos);
57 
58 }
59 double& Matrix::at(int i, int j)
60 {
61     return const_cast<double&>(static_cast<const Matrix*>(this)->at(i, j));
62 }
63 int Matrix::rows() const
64 {
65     return n_rows;
66 }
67 int Matrix::cols() const
68 {
69     return n_cols;
70 }
71 void Matrix::print() const
72 {
73     int num = 0;
74     for (int i = 0; i < n_cols * n_rows; i++)
75     {
76         std::cout << *(ptr + i) << ' ';
77         num++;
78         if (num % n_cols == 0)
79             std::cout << '\n';
80     }
81 }
matrix.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 }
task4.cpp

image

 

实验任务五:

答:

 

 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 }
cantact.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 {
 76     for (int i = 0; i < contacts.size();i++)
 77     {
 78         if (name == contacts[i].get_name())
 79             return i;
 80     }
 81     return -1;
 82 }
 83 
 84 
 85 
 86 // 待补足2:void ContactBook::sort();实现
 87 // 按姓名字典序升序排序通讯录
 88 void ContactBook::sort()
 89 {
 90     int i, j, k = 0;
 91     for (i = 0; i < contacts.size() - 1; i++)
 92     {
 93         k = i;
 94         for (j = i + 1; j < contacts.size(); j++)
 95         {
 96             if (contacts[k].get_name() > contacts[j].get_name())
 97                 k = j;
 98         }
 99         if (k != i)
100         {
101             Contact temp = contacts[k];
102             contacts[k] = contacts[i];
103             contacts[i] = temp;
104         }
105     }
106 
107 }
contactBook.hpp
 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 }
task5.cpp

 

 

 

image

 

实验总结:

功能相同的const与非const成员函数通过static_cast和const_cast可以用一个函数实现两个函数,减少接口。

 

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/976569.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

java---gradle的使用总结

最近做java项目,使用Gradle进行项目构建,从最开始的懵,到现在还是会用了,简单总结下: 1、Gradle是国外的,下载安装比较慢,可以先下载Gradle进行本地安装打开腾讯云Gradle镜像页面:https://mirrors.cloud.tence…

二叉树 节点的个数关系

度数为2的节点a个度数为1的节点b个度数为0的节点c个2a+b=a+b+c-1a=c-1也就是说度数为2的节点的个数=度数为0的节点个数减去1 n2=n0-1 n0=n2+1

整合 MyBatis 代码生成器插件

1. mybatis-generator 是什么?mybatis-generator-maven-plugin 是一个 Maven 插件,用于生成 MyBatis 的代码(如 Mapper 接口、Mapper XML 文件等),官方文档地址: https://mybatis.org/generator/ 。它可以根据数据…

java---Idea

开发java项目使用idea: 下载地址:https://www.jetbrains.com/idea/蓝色的是收费版本,功能很全,有30天试用: 黑色的功能少,免费使用。 IDEA项目结构介绍:然后打开软件:第一步:创建项目 可以选择创建一个空项目:…

java---基础

最近学了学java,做一些整理和梳理:菜鸟笔记https://www.runoob.com/java/java-tutorial.html1、写一个基本的方法: 右键点击【src】选择【新建】【类】勾选【创建一个主方法】然后点击创建即可。 创建一个方法:pub…

内存马研判

内存马如何进行研判? 内存马本身无文件、在内存中运行,无文件的web后门,成功标志是攻击者能够通过特制的HTTP请求与它进行交互,并成功执行命令,获取回显或建立更高级的C2信道。 内存马大致分为:明文/弱加密内存马…

实用指南:__工艺数据管理的范式转变:金仓数据库替代MongoDB实操实践__

pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !important; font-family: "Consolas", "Monaco", "Courier New", …

KEYDIY KD NB27-3 3-Button Universal Flip Remote - 5pcs for Audi Universal Fit

Struggling to Find Reliable Audi Remotes? Meet the KEYDIY KD NB27-3 Universal Flip Remote The Problem: Affordable, Universal Audi Remotes Are Hard to Come By For European and American automotive repai…

NOIP 集训 day3 图论1

MST 相关 知识点:Kruskal Prim Kruskal 重构树洛谷 P4768 [NOI2018] 归程 经典题。先对海拔建出 kruskal 重构树,然后从起点开始通过海拔 \(>p\) 的点可达的所有点就是一个 \(v\) 的一个祖先(深度最小的满足海拔…

计算机网络—TCP和UDP

TCP 和 UDP 有什么区别? TCP:提供了可靠、面向连接的传输,适用于需要数据完整性和顺序的场景 UDP:提供了更轻量、面向报文的传输,适用于实时性要求高的场景 区别总结:对比项 TCP UDP连接方式 面向连接(三次握手…

Universal 3-Button Flip Remote Key for Hyundai: KEYDIY KD NB25-3 (5pcs/lot)

The Hyundai Key Replacement Solution: KEYDIY KD NB25-3 PCF Universal Flip Remote Key Problem: Frustration with Hyundai Key Replacements For European and American Hyundai owners and repair shops, tradit…

接口自动化平台用例执行引擎 — ApiTestEngine

前言 ApiTestEngine 主要是为了快速进行接口自动化平台开发,基于 unittest 设计的接口用例执行引擎,其实之前开发的接口自动化框架 apin 也可以作为测试平台的用例执行引擎。但是 apin 最初设计的初衷是基于 JSON 或…

NOIp 知识点复习

1. Floyd //exam: B3647 【模板】Floyd #include <iostream> #include <cstring> #include <cstdio> #define int long long using namespace std; const int MAXN = 105; int f[MAXN][MAXN]; int n…

Redis:高性能NoSQL数据库实战指南 - 教程

Redis:高性能NoSQL数据库实战指南 - 教程2025-11-25 22:46 tlnshuju 阅读(0) 评论(0) 收藏 举报pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: bloc…

2025年口碑好的轮胎品牌哪家好:十大消费者信赖品牌揭秘

2025年口碑好的轮胎品牌哪家好:十大消费者信赖品牌揭秘在当前消费端愈发重视驾乘体验与安全信赖的市场语境下,“口碑好的轮胎品牌哪家好”正迅速跃升为车主、采购决策者与行业观察者共同聚焦的核心议题。伴随新能源汽…

Topic 2

Topic 2 目录Python 内建数据结构概览 List(列表) - 列表特性 - 创建方法、访问方式、修改方式 - 添加、插入、删除、排序、遍历 - 方法总表 - 例子逐行解释 Tuple(元组) - 特性、创建、访问 - 不可变性质、如何绕…

2025年反渗透一体机/软化水设备/中水再生水回用设备/净水处理设备厂家最新权威推荐:产能、专利、环保三维数据透视,行业数据用户口碑,工业/家用选择指南

随着城镇化进程加快与环保政策收紧,净水、纯水、软化水设备成为解决村镇饮水安全、工业用水净化的核心装备。本榜单基于技术实力、区域适配性、案例验证三大维度,结合《2024中国水处理设备行业发展报告》及环保项目招…

AcWing 860:染色法判定二分图 ← 并查集

​【题目来源】https://www.acwing.com/problem/content/862/【题目描述】给定一个 n 个点 m 条边的无向图,图中可能存在重边和自环。请你判断这个图是否是二分图。【输入格式】第一行包含两个整数 n 和 m。接下来 m …

回调函数20251125

1.回调函数:将函数作为指针传参给其他函数使用,实现解耦作用,将各个功能分开。举例,不含参数的回调函数:#include"stdio.h" int Callback() { printf("Hello, this is Callback "); re…

类模板的实现

pragma once include using namespace std; template class Myvector { friend ostream& operator<< (ostream& out, const Myvector & othervectr); //用有元函数重载输出运算符 ,注意必须要加…