2023/9/8 -- C++/QT

作业

1> 自行封装一个栈的类,包含私有成员属性:栈的数组、记录栈顶的变量

成员函数完成:构造函数、析构函数、拷贝构造函数、入栈、出栈、清空栈、判空、判满、获取栈顶元素、求栈的大小

02stack.h:

#ifndef __02STACK_H__
#define __02STACK_H__
#include <iostream>#define MAX 10      //栈的容量
using namespace std;class Stack{
private:int *data;      //栈的数组int top;        //栈顶下标
public://构造函数Stack();//析构函数~Stack();//拷贝构造函数Stack(const Stack &other);//判空bool empty();//判满bool full();//入栈int push();//出栈int pop();//清空栈int clear();//获取栈顶元素int get_top_value();//求栈的大小int size();
};#endif // 02STACK_H

02stack.cpp:

#include "02stack.h"//构造函数
Stack::Stack():data(new int[MAX]),top(-1){      //栈顶从-1开始cout<<"初始化成功!"<<endl;//cout<<"构造函数"<<endl;
}
//析构函数
Stack::~Stack(){delete []data;//cout<<"析构函数"<<endl;
}
//拷贝构造函数
Stack::Stack(const Stack &other){top = other.top;data = new int[MAX];for(int i = 0;i <= top;i++){data[i] = other.data[i];}cout<<"拷贝成功!"<<endl;//cout<<"拷贝构造函数"<<endl;
}
//判空
bool Stack::empty(){return top == -1;
}
//判满
bool Stack::full(){return top >= MAX-1;
}
//入栈
int Stack::push(){if(full()){cout<<"栈满!入栈失败!"<<endl;return -1;}int value;cout<<"请输入您要入栈的元素:";cin>>value;top++;data[top] = value;cout<<value<<"  入栈成功!"<<endl;//cout<<"top = "<<top<<endl;return 0;
}
//出栈
int Stack::pop(){if(empty()){cout<<"栈空!出栈失败!"<<endl;return -1;}int temp = data[top];data[top] = 0;top--;cout<<temp<<"  出栈成功!"<<endl;return 0;
}
//清空栈
int Stack::clear(){data[top] = 0;while (top-->0) {data[top] = 0;}cout<<"清空栈成功!"<<endl;return 0;
}
//获取栈顶元素
int Stack::get_top_value(){cout<<"栈顶元素为:"<<data[top]<<endl;return 0;
}
//求栈的大小
int Stack::size(){cout<<"栈的大小为:"<<top+1<<endl;return 0;
}

 main.cpp:

#include "02stack.h"int main()
{Stack s;s.push();s.push();s.push();s.get_top_value();s.size();Stack s1 = s;s1.size();s1.get_top_value();s.pop();s.clear();s.size();return 0;
}

效果图:

2> 自行封装一个循环顺序队列的类,包含私有成员属性:存放队列的数组、队头位置、队尾位置

成员函数完成:构造函数、析构函数、拷贝构造函数、入队、出队、清空队列、判空、判满、求队列大小

03queue.h:

#ifndef __03QUEUE_H__
#define __03QUEUE_H__
#include <iostream>#define MAX 10
using namespace std;class Queue{
private:int front;int back;int *data;
public://构造函数Queue();//析构函数~Queue();//拷贝构造函数Queue(const Queue &other);//判空bool empty();//判满bool full();//入队int push();//出队int pop();//清空队列int clear();//求队列大小int size();
};#endif // 03QUEUE_H

03queue.cpp:

#include "03queue.h"//构造函数
Queue::Queue():front(0),back(0),data(new int[MAX]){cout<<"初始化成功"<<endl;cout<<"构造函数"<<endl;
}
//析构函数
Queue::~Queue(){delete []data;cout<<"析构函数"<<endl;
}
//拷贝构造函数
Queue::Queue(const Queue &other){front = other.front;back = other.back;data = new int[MAX];if(front < back){for(int i = front;i < back;i++){data[i] = other.data[i];}}if(front > back){for(int i = front;i < back+MAX;i++){data[i%MAX] = other.data[i%MAX];}}//cout<<"q1.front = "<<front<<endl;//cout<<"q1.back = "<<back<<endl;//cout<<"front = "<<other.front<<endl;//cout<<"back = "<<other.back<<endl;cout<<"拷贝构造函数"<<endl;
}
//判空
bool Queue::empty(){return front == back;
}
//判满
bool Queue::full(){return (back+1)%MAX == front;
}
//入队
int Queue::push(){if(full()){cout<<"队列已满!入队失败!"<<endl;return -1;}int value;cout<<"请输入您要入队的元素:";cin>>value;data[back] = value;back = (back+1)%MAX;//cout<<"front = "<<front<<endl;//cout<<"back = "<<back<<endl;cout<<value<<"  入队成功!"<<endl;return 0;
}
//出队
int Queue::pop(){if(empty()){cout<<"队列已空!出队失败!"<<endl;return -1;}int temp = data[front];data[front] = 0;front = (front+1)%MAX;//cout<<"front = "<<front<<endl;//cout<<"back = "<<back<<endl;cout<<temp<<"  出队成功!"<<endl;return 0;
}
//清空队列
int Queue::clear(){if(front < back){for(int i = front;i < back;i++){data[i] = 0;}}if(front > back){for(int i = front;i < back+MAX;i++){data[i%MAX] = 0;}}front = back = 0;//cout<<"front = "<<front<<endl;//cout<<"back = "<<back<<endl;cout<<"清空队列成功!"<<endl;return 0;
}
//求队列大小
int Queue::size(){cout<<"队列大小为:"<<(back+MAX-front)%MAX<<endl;return 0;
}

 main.cpp:

#include "03queue.h"int main()
{Queue q;q.push();q.push();q.push();q.size();Queue q1 = q;q1.size();q.pop();q.pop();q.size();q.push();q.clear();return 0;
}

效果图:

一、类

1.1 类的定义格式

class 类名
{public:公共的成员变量、成员函数的定义;protected:受保护的成员变量、成员函数;private:私有的成员变量、成员函数;
};//注意
1、类中是有访问权限控制public该权限下的成员,可以在类内、子类中、类外被访问protected该权限下的成员,可以在类内、子类中被访问,类外不能被访问private:该权限下的成员可以在类内被访问,子类中和类外都无权访问
2、类中的访问权限是针对于类体而言的,跟类对象没有关系
3、如果没有给定访问权限,默认是私有的访问权限
4、每个访问权限可以出现多次,可以出现在类内的任何位置,每种访问权限的作用域是从该关键字开始到下一个关键字或整个类体结束为止
5、我们通常将某个权限下的所有成员放到一个访问权限关键字下
6、通常成员属性一般定义成私有权限,成员函数一般定义成公有权限
7、类中的成员函数可以访问类中的任意权限下的成员,包括私有成员

1.2 类的大小

1> 一个空类的大小为1字节,起到占位作用,如果有成员属性,则会将这一字节分配给成员属性

2> 类的大小也跟结构体一样遵循字节对齐

3> 类中的普通成员函数不占类的大小,即使成员函数中有变量

4> 类中如果存在虚函数,那么会默认提供一个指针的大小(后期讲)

1.3 C++中结构体与类的区别

1> C++中结构体跟类没什么太大区别,主要的区别是默认访问权限和默认继承方式不同

2> C++中结构体的默认访问权限是public,而类的默认访问权限是private

3> C++中结构体的默认继承方式是public,而类的默认继承方式是private

4> 使用场景:一般实现数据结构的相关操作,我们使用结构体完成,其他有关类对象的实现,我们使用类来完成

二、this指针

2.1 引入目的

在类的定义过程中,有可能需要使用一个变量来指代类对象本身,用来找该类中的成员属性或成员变量,此时C++编译器会给类中所有非静态成员函数提供一个隐藏的形参指针this,表明指代该类本身,哪个对象使用我,我就指向哪个对象的起始地址。

2.2 this的原型推导

1> 原型:类名 * const this;

2> 可以通过this指针更改类中的内容,但是不能更改this的指向

3> 只有成员函数中才能使用this指针,是每个非静态成员函数都拥有的一个隐藏形参

2.3 必须使用this的场景

1> 当非静态成员函数中,函数的形参名或局部变量名与类的成员名同名时,在函数体内必须使用this指针加以区分,否则使用的是局部变量

2> 在拷贝赋值函数中,需要返回自身的引用时,需要使用this指针

三、类中特殊的成员函数

当定义一个类时,编译器会给类体提供一些特殊的函数。

特殊原因:如果没有显性定义这些函数,系统会默认提供这些函数,如果显性定义了这些函数,系统就不再提供默认的了

这些函数无需显性调用,特殊时期系统会自动调用

特殊函数:构造函数、析构函数、拷贝构造、拷贝赋值、移动构造、移动赋值、取地址运算符重载、常取地址运算符重载

3.1 构造函数

1> 功能:使用类实例化对象时,用于给类对象申请资源并初始化用的

2> 定义格式

1、函数名与类同名
2、没有返回值,连void都没有
3、权限:一般为public
4、参数:可以有也可以没有参数,构造函数可以重载
5、格式:类名(形参列表){函数体内容}

3> 调用时机

在使用类实例化对象过程中,系统自动调用该函数,无需手动调用

栈区:实例化对象时,系统自动调用构造函数

                类名 对象名(实参列表); //此时系统会自动调用构造函数

堆区:定义类对象指针时,不会调用构造函数,当使用new关键字给类对象申请空间时会自动调用构造函数

                类名 *指针名; //此时不会调用构造函数

                指针名 = new 类名(实参列表); //此时才会调用构造函数

4> 注意:

1、如果类内没有显性定义任何构造函数,系统会默认提供一个无参构造函数,

2、如果显性定义了任意一种有参构造函数,系统就不再提供无参构造函数了,如果非要使用无参构造函数,需要显性再定义出无参构造函数

3、 一个类中,可以定义多个构造函数,这多个构造函数构成重载关系

4、构造函数的也支持默认参数

#include <iostream>using namespace std;
class Stu
{
private:string name;int age;double score;public://显性定义无参构造函数Stu(){cout<<"Stu::无参构造"<<endl;}Stu(string n){name = n;           //给成员变量n进行赋值cout<<"Stu::一个参数的构造函数"<<endl;}//带默认参数的构造函数Stu(string n, int a, double s = 90){name = n;age = a;score = s;cout<<"Stu::所有参数的构造函数"<<endl;}//定义成员函数void show(){cout<<"name = "<<name<<endl;cout<<"age = "<<age<<endl;cout<<"score = "<<score<<endl;}
};int main()
{Stu s1;          //在栈区实例化一个学生对象s1.show();        //随机值cout<<"***************************************"<<endl;Stu *p1;          //不会调用构造函数p1 = new Stu;       //此时会调用构造函数p1->show();cout<<"***************************************"<<endl;Stu s2("zhangpp");s2.show();cout<<"***************************************"<<endl;Stu s3("zhangsan", 18);s3.show();return 0;
}

5> 构造函数可以设置初始化列表

1、使用格式:在构造函数的形参列表后,由冒号引出初始化列表,完成初始化工作

        类名(类型1 形参1, 类型2 形参2,。。。,类型n 形参n):成员1(形参1),成员2(形参2),。。。,成员n(参数n)

        {

                函数体内容;

        }

2、注意:在初始化列表中,括号内是形参数据,括号外是成员数据,不要写反

6> 构造函数必须使用初始化列表的情况

1、当类中的成员有引用成员时,必须在初始化列表中对该引用成员进行初始化

2、当类中有const修饰的成员变量时,对该成员的的初始化也必须放在初始化列表中

3、当构造函数的形参名和成员变量名同名时,可以使用初始化列表来解决初始化问题

4、当类中有其他类的对象作为成员变量时,对该类对象的初始化工作也必须在初始化列表中完成,需要在初始化列表中显性调用成员对象的有参构造完成初始化工作,如果没有显性调用成员对象的有参构造,系统会自动调用该成员对象的无参构造来完成对该成员对象的初始化工作

3.2 析构函数

1> 功能:在类对象消亡时,用于回收类对象的资源空间用的

2> 定义格式

1、函数名是在类名前加~:~类名
2、参数:无
3、返回值:没有
4、权限:一般为public
5、格式:~类名(){}

3> 调用时机:

栈区:类对象的作用域结束时,系统会自动调用该类的析构函数,完成对对象的内存回收。

堆区:何时使用delete何时调用析构函数,一直不调用,一直不析构

4> 注意:

1、如果类中没有显性定义析构函数,系统会默认提供一个析构函数完成对成员内存的回收工作

2、如果类中显性定义了析构函数,系统就不再提供,默认的析构函数了

3、构造和析构的顺序:

        栈区:先构造的后析构,后构造的先析构(在同一作用域下)

        堆区:何时使用delete何时调用析构函数

4、如果类中没有指针成员,那么使用系统提供的析构函数就足够完成对类对象的内存回收

        如果类中有指针成员,并指向堆区空间,需要显性定义析构函数,在析构函数的函数体内,将成员指针指向的空间进行释放,否则会内存泄漏

5、一个类中析构函数只能有一个

3.3 拷贝构造函数

1> 拷贝构造函数是一个特殊的构造函数,功能是:使用一个类对象给另一个类对象初始化时,系统自动调用

                string s1("hello world"); //有参构造

                string s2 = s1; //调用拷贝构造

                string s3(s2); //拷贝构造函数

2> 定义格式

1、函数名与类同名
2、没有返回值
3、参数:同类的其他类对象的引用
4、权限:一般为public
5、格式:类名(const 类名 &other){}

3> 调用时机:

1、使用一个类对象给另一个类对象初始化时,系统自动调用

2、函数形参时类对象时,实参向形参传递时,也会调用拷贝构造函数

3、函数返回值是类对象时,函数调用时也会调用拷贝构造函数

4> 注意事项:

1、如果没有显性定义拷贝构造函数,系统会默认提供一个拷贝构造函数,来完成对象成员之间的简单赋值

2、如果显性定义了拷贝构造函数,系统就不再提供默认的拷贝构造函数了

5> 深浅拷贝

1、在一个类中,如果没有显性定义拷贝构造函数,系统会默认提供一个拷贝构造函数,来完成类对象之间的简单赋值,这个拷贝构造函数是一个浅拷贝,如果类中无指针成员,那么使用该拷贝构造函数没有问题

2、如果类中有指针成员并且指向堆区空间,使用浅拷贝就会造成对同一个堆区空间的多次释放问题,会产生double free的段错误

3、此时就需要显性定义拷贝构造函数完成深拷贝:在拷贝构造函数的初始化列表中,给自己的指针成员重新申请出一个空间,将原对象的指针成员指向的空间内容赋值过来,即可完成深拷贝

#include <iostream>using namespace std;
class Stu
{
private:string name;int age;double score;public://显性定义无参构造函数Stu(){cout<<"Stu::无参构造"<<endl;}//带默认参数的构造函数Stu(string n, int a, double s ):name(n),age(a),score(s){cout<<"Stu::有参构造函数"<<endl;}//定义析构函数~Stu(){cout<<"Stu::析构函数:"<<this<<endl;}//定义拷贝构造函数Stu(const Stu &other):name(other.name), age(other.age), score(other.score){cout<<"拷贝构造函数"<<endl;}//定义成员函数void show(){cout<<"name = "<<name<<endl;cout<<"age = "<<age<<endl;cout<<"score = "<<score<<endl;}
};//定义一个全局函数,实参向形参传递时调用拷贝构造,函数返回时也会调用拷贝构造
Stu fun(Stu s)                 //int num = 520;
{s.show();return  s;
}int main()
{Stu s1("zhangpp", 18, 90);         //调用有参构造函数fun(s1);return 0;
}

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

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

相关文章

网络协议从入门到底层原理学习(三)—— 路由

网络协议从入门到底层原理学习&#xff08;三&#xff09;—— 路由 1、简介 路由&#xff08;routing&#xff09;是指分组从源到目的地时&#xff0c;决定端到端路径的网络范围的进程 在不同网段之间转发数据&#xff0c;需要有路由器的支持 默认情况下&#xff0c;路由器…

linux并发服务器 —— 项目实战(九)

阻塞/非阻塞、同步/异步 数据就绪 - 根据系统IO操作的就绪状态 阻塞 - 调用IO方法的线程进入阻塞状态&#xff08;挂起&#xff09; 非阻塞 - 不会改变线程的状态&#xff0c;通过返回值判断 数据读写 - 根据应用程序和内核的交互方式 同步 - 数据的读写需要应用层去读写 …

[VSCode] 替换掉/去掉空行

VSCode中使用快捷键CtrlH&#xff0c;出现替换功能&#xff0c;在上面的“查找”框中输入正则表达式&#xff1a; ^\s*(?\r?$)\n然后选择右侧的“使用正则表达式”&#xff1b;“替换”框内为空&#xff0c;点击右侧的“全部替换”&#xff0c;即可去除所有空行。 参考 [VS…

MySQL 连接出现 Authentication plugin ‘caching_sha2_password‘ cannot be loaded

在使用Navicat Premium 12连接MySQL数据库时会出现Authentication plugin caching_sha2_password cannot be loaded 出错 出现这个原因是mysql8 之前的版本中加密规则是mysql_native_password,而在mysql8之后,加密规则是caching_sha2_password, 解决问题方法&#xff1a;把my…

Linux内核分析与应用2-内存寻址

本系列是对 陈莉君 老师 Linux 内核分析与应用[1] 的学习与记录。讲的非常之好&#xff0c;推荐观看 留此记录&#xff0c;蜻蜓点水,可作抛砖引玉 2.1 内存寻址 数据连续存储和选择读取思想,是目前我们使用的几乎所有机器运行背后的灵魂 计算机体系结构中的核心问题之一,就是如…

AP5101C 高压线性恒流IC 宽电压6-100V LED汽车大灯照明 台灯LED矿灯 指示灯电源驱动

产品描述 AP5101C 是一款高压线性 LED 恒流芯片 &#xff0c; 外围简单 、 内置功率管 &#xff0c; 适用于6- 100V 输入的高精度降压 LED 恒流驱动芯片。电流2.0A。AP5101C 可实现内置MOS 做 2.0A,外置 MOS 可做 3.0A 的。AP5101C 内置温度保护功能 &#xff0c;温度保护点为…

力扣(LeetCode)算法_C++——稀疏矩阵的乘法

给定两个 稀疏矩阵 &#xff1a;大小为 m x k 的稀疏矩阵 mat1 和大小为 k x n 的稀疏矩阵 mat2 &#xff0c;返回 mat1 x mat2 的结果。你可以假设乘法总是可能的。 示例 1&#xff1a; 输入&#xff1a;mat1 [[1,0,0],[-1,0,3]], mat2 [[7,0,0],[0,0,0],[0,0,1]] 输出&am…

mysql 增量备份与恢复使用详解

目录 一、前言 二、数据备份策略 2.1 全备 2.2 增量备份 2.3 差异备份 三、mysql 增量备份概述 3.1 增量备份实现原理 3.1.1 基于日志的增量备份 3.1.2 基于时间戳的增量备份 3.2 增量备份常用实现方式 3.2.1 基于mysqldump增量备份 3.2.2 基于第三方备份工具进行增…

Vue中表单手机号验证与手机号归属地查询

下面是一篇关于Vue中如何进行表单手机号验证与手机号归属地查询的Markdown格式的文章&#xff0c;包含代码示例。 Vue中表单手机号验证与手机号归属地查询 手机号验证和归属地查询是许多Web应用程序中常见的功能之一。在Vue.js中&#xff0c;我们可以轻松地实现这两个功能。本…

如何使用Web Storage对页面中数据进行监听?

当使用Web Storage存储的数据发生变化时&#xff0c;会触发Window对象的storage事件&#xff0c;我们可以监听该事件并指定事件处理函数&#xff0c;当其他页面中的localStorage或 sessionStorage中保存的数据发生改变时&#xff0c;就会执行事件处理函数。 监听storage事件的…

SpotBugs(是FindBugs的继任者)安装、使用

SpotBugs介绍 SpotBugs和FindBugs的关系 SpotBugs是FindBugs的继任者&#xff0c;从SpotBugs停止的地方继续。 备注&#xff1a;FindBugs项目已经停止了&#xff0c;从2015年发布3.0.1版本以后再没有新的版本。 SpotBugs通过静态分析寻找java代码中的bug&#xff0c;通过发现…

JavaScript 运行时比较: Node.js、 Deno 和 Bun

文章目录 为什么选择正确的 JavaScript 运行时很重要介绍 JavaScript 运行时Node.jsDenoBun 比较 JavaScript 运行时性能社区稳定性安全附加功能 小结 JavaScript 运行时可帮助您构建高级的、服务器驱动的 JavaScript 项目&#xff0c;这些项目不依赖于用户的浏览器来运行。 有…

Linux 安装配置使用 FTP 服务

学习场景&#xff1a;使用摄像机做区域报警&#xff0c;预警后将预警图片传输到 FTP 服务上&#xff0c;所以搭一个环境测试一下&#xff0c;这里我使用的是树莓派 4B&#xff0c;官方 32 位系统&#xff0c;其他 Linux 系统应该通用 下面说两个 FTP 应用 一、vsftpd vsftpd 是…

基于python实现贪心算法、蛮力法、动态规划法解决分数背包问题和0-1背包问题(附完整源码下载)

背包问题算法设计 问题要求在一个物品集合中选择合适的物品放入背包&#xff0c;在放入背包中的物品总重量不超过背包容量的前提下&#xff0c;希望放入背包的物品总价值最大。根据是否允许部分物品放入背包的要求&#xff0c;背包问题可以分为【分数背包问题】和【0-1背包问题…

形态图像处理

形态图像处理 预备知识 反射、平移结构元 腐蚀和膨胀 腐蚀 将 B 平移&#xff0c;当其原点位于 z 时&#xff0c;其包含在 A 中&#xff0c;则 z 为一个有效的位置&#xff0c;所有有效的z构成了腐蚀之后的结果腐蚀缩小或细化了二值图像中的物体可以将腐蚀看作形态学滤波操…

Solidity 小白教程:12. 事件

Solidity 小白教程&#xff1a;12. 事件 这一讲&#xff0c;我们用转账 ERC20 代币为例来介绍solidity中的事件&#xff08;event&#xff09;。 事件 Solidity中的事件&#xff08;event&#xff09;是EVM上日志的抽象&#xff0c;它具有两个特点&#xff1a; 响应&#x…

探索云计算和大数据分析的崛起:API行业的机遇与挑战【电商大数据与电商API接入】

I. 引言 随着云计算和大数据分析技术的快速发展&#xff0c;企业和个人对数据分析和处理的需求不断增加。在这个信息爆炸的时代&#xff0c;数据已成为企业决策和战略规划的重要基础。云计算提供了强大的计算和存储能力&#xff0c;使得大规模数据的处理和分析变得更加容易和高…

科技成果鉴定测试报告一般包含哪些测试内容?

软件测评报告 一、科技成果评价是需要做第三方软件测评报告&#xff0c;一般是证明技术指标点是否完善&#xff0c;覆盖主要申报内容&#xff0c;应用软件项目科技成果鉴定测试内容&#xff1a; &#xff08;一&#xff09;是否完成合同或计划任务书要求的指标&#xff1b; …

List常见面试问题

List的特点有哪些&#xff1f; Java中的List是一种存放有序的、可以重复的数据的集合&#xff0c;它允许重复元素的存在。List中的元素都有对应的一个序列号(索引)记录着元素的位置&#xff0c;因此可以通过这个序列号来访问元素。 ‍ Java中集合有哪些&#xff1f; Java中…

Ubuntu tmux 默认安装 快捷键

安装 sudo apt install tmux 启动tmux tmux 注意下方已显示[0] 0:bash 左右分屏 依次输入两组快捷键&#xff1a;Ctrlb, Shift5 即:% 上下分屏 依次输入两组快捷键&#xff1a;Ctrlb, Shift 即:" 切换窗口&#xff08;注意&#xff1a;鼠标点击没有切换效果&#x…