类和对象(2)

文章目录

  • 1.类的6个默认成员函数(天选之子)
  • 2.构造函数
  • 3.析构函数
    • 3.1特性
  • 4.拷贝构造

1.类的6个默认成员函数(天选之子)

C语言中,可能中途return也可能最后return,destroy的地方很多,比较麻烦。
以下为C++进行的改进,俗称”天选之子“。
在这里插入图片描述

  • 构造函数和析构函数如果不写,编译器则会自动生成一个默认
  • 如果我们实现了任意一个,编译器就会自动生成了。
  • 对象在实例化的时候必须调用构造函数(包括自己写的和编译器自动生成的),应调用自己生成的那个。

C++类型分为:内置类型(int,char,任意类型的指针)不处理,
自定义类型(class,struct,union联合体)调用他的构造
默认生成的构造函数对于内置类型的成员不做处理,对于自定义类型的成员,会去调用它的构造(不用传参的构造)
与析构函数相似

class Date
{
public:Date(){_year = 1;_month= 1;_day= 1;}Date(int year, int month, int day)//带参的初始化{_year = year;_month = month;_day = day;}void Print(){cout << _year << "年" << _month << "月" << _day << "日" << endl;}
private:
//基本类型或内置类型,因为带intint _year;int _month;int _day;
};
int main()
{Date d1;Date d2(2023, 9, 13);d1.Print();d2.Print();return 0;
}

在这里插入图片描述

合并两个构造函数,用全缺省更好用

	Date(int year=1, int month=1, int day=1)//全缺省{_year = year;_month = month;_day = day;}

两个栈实现一个队列(push,pop,peek,empty)问题。
在这里插入图片描述
C

typedef struct {ST pushst;ST popst;
}MyQueue;
bool myQueueEmpty(MyQueue* obj);
MyQueue* myQueueCreate()
{MyQueue* pq = (MyQueue*)malloc(sizeof(MyQueue));StackInit(&pq->pushst);StackInit(&pq->popst);return pq;
}
void myQueueFree(MyQueue* obj)
{assert(obj);StackDestroy(&obj->pushst);StackDestroy(&obj->popst);return pq;
}

C++

class MyQueue {
public://默认生成的构造函数,对自定义类型,会调用他的默认构造函数。void push(int x){}//...Stack _pushST;Stack _popST;
};
int main()
{MyQueue q;return 0;
}

2.构造函数

实际上是在初始化对象特殊的成员函数。作用和Init相同。,主要任务不是开空间创造对象,而是初始化对象

  1. 函数名和类名相同。名字已经定好了
  2. 没有返回值,什么也不用写。
  3. 对象实例化时自动调用对应的构造函数需要调用显示的Init
  4. 可以重载(一个类可以有多个构造函数),有多个构造函数就有多种初始化方式
  5. 如果类中没有显式定义构造函数,则C++编译器会自动生成一个无参的默认构造函数,对于内置类型不做处理,对于自定义类型会去调用它的构造函数。一旦用户显式定义编译器再生成。
  6. 无参全缺省的构造函数都被称为默认构造函数,且仅有一个,同时调用时存在歧义。不写编译器自动生成的也是默认构造函数。不传参数就可以调用构造函数。一般建议每个类都提供一个默认构造函数。
#include <iostream>
using namespace std;
class Stack
{
public://成员函数void Init(int n=4){_a = (int*)malloc(sizeof(int) * n);if (nullptr == a){perror("malloc申请空间失败");return;}capacity = n;size = 0;}void Push(int x){//...a[size++] = x;}void Destroy(){//...防止内存泄漏,可以把这件事交给编译器,让他自动搞起来。}//...
private://成员变量int* _a;int _size;int _capacity;
};
int main()
{//定义一个栈Stack st;//初始化st.Init(4);st.Push(1);st.Push(1);st.Push(1);st.Push(1);//进行销毁st.Destroy();return 0;
}
class Stack
{
public:Stack(){_a = nullptr;_size = _capacity = 0;}Stack(int n)//有了构造函数的类就不需要Init的类//构成函数重载{_a = (int*)malloc(sizeof(int) * n);if (nullptr == _a){perror("malloc申请空间失败");return;}_capacity = n;_size = 0;}void Push(int x){//..._a[_size++] = x;}void Destroy(){//...防止内存泄漏,可以把这件事交给编译器,让他自动搞起来。}
private://成员变量int* _a;int _size;int _capacity;
};
int main()
{//构造函数的调用//定义一个栈//Stack st;//无参,不带(),否则会报错//因为是声明函数还是调用对象分不清楚。有点混淆Stack st(4);//带参//Stack st(4,3);st.Push(1);st.Push(1);st.Push(1);st.Push(1);//进行销毁st.Destroy();return 0;
}

Stack st(4)不等同于st.Stack(4)
构造函数不能用对象调用,st定义好了才向下走。

3.析构函数

destroy,和刚才构造函数的方法类似,定义一个函数让他自动调用。功能和构造函数相反,析构函数不是完成对象本身的销毁,析构函数进行清理资源在对象出了作用域,生命周期销毁后进行调用

3.1特性

  1. 函数名是在类名前加==~==。C语言中代表按位取反。
  2. 参数返回值。
  3. 一个类只有一个析构函数,若未显式定义,系统则**自动生成默认的析构函数。**注意:析构函数不能重载。
  4. 生命周期结束时,C++编译系统自动调用析构函数
~Stack()
{free(_a);_a=nullptr;_size=_capacity=0;
}//只定义一个对象就释放一次,两个对象释放2次

在这里插入图片描述

4.拷贝构造

  1. 构造函数的一个重载,函数名和类名相同,没有返回值。
  2. 参数只有一个且必须是类类型对象的引用,使用传值编译器直接报错,因为会引发无穷递归调用
Date(Date d){_year = d._year;_month = d._month;_day = d._day;//拷贝构造}//编译器不允许发生这种拷贝构造,会产生无穷递归,规定这个地方必须用引用

//普通整型,内置类型可以直接传递,但是自定义类型不可以

//传值传参
void Func1(Date d)
{}//Func传参的时候是一个拷贝,把d1拷贝给d
//传引用传参
void Func2(Date& d)
{
}//d是d1的别名
int main()
{
Func1(d1);
return 0;
}
  1. 自定义类型不能编译器随便拷贝。内置类型编译器可以直接拷贝,自定义类型的拷贝需要调用拷贝构造。

  2. 字节拷贝:浅拷贝

  3. 对于栈来说,浅拷贝两个栈指定同一空间,会析构两次。

  4. C++规定自定义类型要调用一个拷贝构造,栈这样的类要调用一个深拷贝自己去开一块空间)的拷贝构造。

  5. 调用func1先传参,传参就是一个拷贝构造

  6. Date d2(d1);//对象实例化调用,先调用对应的构造函数,此时是拷贝构造Date (Date d);,调用拷贝构造之前要先传参d1传给d,传值传参又形成一个拷贝构造;拷贝构造要先传参,传值传参又是一个拷贝构造。。。。。递归下去。套娃
    解决方法:引用。Date (Date &d);//d是d1的别名

  7. 拷贝构造也可以这么写:Date d2=d1;
    拷贝构造一般加const

  8. Date (const Date &d);//权限缩小,权限可以缩小不可放大。

  9. 引用不需要调用函数。调用就是传参

  10. 指针也是内置类型自定义类型必须用拷贝构造完成,编译器驾驭不了。

Date(const Date* d)
{cout<<"Date(Date& d)"<<endl;_year = d->_year;_month = d->_month;_day = d->_day;//不是拷贝构造
}//只是一个普通的构造函数Date d4(&d1);Dare d5=&d1;//复杂别扭

实现一个函数,实现多少天以后的日期。

int GetMonthDay(int year, int month){//if,else/switch,case//数组assert(month > 0 && month < 13);int monthArray[13] = { 0,31,28,31,30,31,30,31,31,30,31,30,31 };if (month == 2 && ((year % 4 == 0 && year % 100 == 0) || (year % 400 = 0))){return 29;}else{return monthArray[month];}}Date GetAfterXDay(int x){//先用一个结果,先生成一个中间临时对象。拷贝d1,this是d1的地址//Date tmp;//tmp._year = _year;//传值返回不用tmp,因为tmp出了作用域后被销毁,返回tmp的拷贝。进行拷贝构造//用同类型对象//Date tmp(*this);拷贝构造Date tmp = *this;//拷贝构造//不能用引用,用引用tmp是d1的别名。tmp的改变就是d1的改变。//不动自己的成员//加法进位tmp._day += x;while (tmp._day > GetMonthDay(tmp._year, tmp._month)){//进位tmp._day -= GetMonthDay(tmp._year, tmp._month);++tmp._month;if (tmp._month == 13){tmp._year++;tmp._month = 1;}}//获取日期//return* this;//返回自己,自己的年月日都在往后加,this是这个对象的指针,*this是这个对象//除了作用于还在return tmp;//局部对象}void Print(){cout << _year << "年" << _month << "月" << _day << "日" << endl;}int main(){Date d1(2023, 9, 13);Date d2 = d1.GetAfterXDay(100);d1.Print();d2.Print();//这时改变_year等会改变d1return 0;}

+(不改变)和+=(改变)返回值的区别。

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

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

相关文章

数据在内存中的存储

目录 数据类型 大小端 判断大小端 练习 1 2 浮点数在内存中储存 存M 存E 取E 数据类型 整形家族&#xff1a; char unsigned char signed char short unsigned short [int] signed short [int] int unsigned int signed int long unsigned long [int] signed…

云原生服务无状态(Stateless)特性的实现

文章目录 为何要使用无状态服务&#xff1f;无状态服务的实现方法1. 会话状态外部化2. 负载均衡3. 自动伸缩4. 容器编排5. 数据存储6. 安全性 示例&#xff1a;使用Spring Boot实现无状态服务结论 &#x1f389;欢迎来到云计算技术应用专栏~云原生服务无状态&#xff08;Statel…

BOM操作

文章目录 BOM事件页面加载调整窗口事件定时器停止计时器Location对象History对象Offsetleft获取元素偏移Offset与style的区别可视区client系列滚动scroll系列Mouseover和mousenter区别 动画原理实现动画封装给不同对象添加定时器缓动动画原理多个位置间移动 BOM事件 页面加载 …

【Tomcat服务部署及优化】

Tomcat 一、什么是Tomcat?二、Tomcat 核心组件2.1 Tomcat 组件2.3 Container组件的结构2.4 Tomcat 请求过程 三、Tomcat 部署3.1 安装JDK3.2 设置JDK环境变量3.3 安装Tomcat并用supervisor启动解压添加到supervisord服务测试能否通过supervisorctl启动 四、Tomcat的端口和主要…

普中51-蜂鸣器实验

蜂鸣器实验 蜂鸣器主要分为压电式蜂鸣器和电磁式蜂鸣器两种类型 压电式蜂鸣器主要由多谐振荡器、压电蜂鸣片、阻抗匹配器及共鸣箱、外壳等组成。多谐振荡器由晶体管或集成电路构成&#xff0c;当接通电源后&#xff08;1.5~15V 直流工 作电压&#xff09;&#xff0c;多谐振荡…

c++ day 6

1、 将之前定义的栈类和队列类都实现成模板类 #include <iostream>using namespace std;#define MAX 128template<typename T>class Stack { public://构造函数Stack();//析构函数~Stack();//拷贝构造函数Stack(const Stack &other);//入栈int push(T e);//出…

​LeetCode解法汇总1222. 可以攻击国王的皇后

目录链接&#xff1a; 力扣编程题-解法汇总_分享记录-CSDN博客 GitHub同步刷题项目&#xff1a; https://github.com/September26/java-algorithms 原题链接&#xff1a;力扣&#xff08;LeetCode&#xff09;官网 - 全球极客挚爱的技术成长平台 描述&#xff1a; 在一个 8x…

Linux学习笔记-Ubuntu系统下配置用户ssh只能访问git仓库

目录 一、基本信息1.1 系统信息1.2 git版本[^1]1.2.1 服务器端git版本1.2.2 客户端TortoiseGit版本1.2.3 客户端Git for windows版本 二、创建git用户和群组[^2]2.1 使用groupadd创建群组2.2 创建git用户2.2.1 使用useradd创建git用户2.2.2 配置新建的git用户ssh免密访问 2.3 创…

AndroidStudio 编译输出中文乱码

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录 前言现象如何解决 前言 Android studio 编译输出乱码 现象 如何解决 在弹出的 studio64.exe.vmoptions 文件中 , 输入如下内容 : -Dfile.encodingUTF-8上述文件配…

基于小程序的理发店预约系统

一、项目背景及简介 现在很多的地方都在使用计算机开发的各种管理系统来提高工作的效率&#xff0c;给人们带来很多的方便。计算机技术从很大的程度上解放了人们的双手&#xff0c;并扩大了人们的活动范围&#xff0c;是人们足不出户就可以通过电脑进行各种事情的管理。信息系…

真空腔体的设计要点

真空腔体是保持内部为真空状态的容器&#xff0c;真空腔体设计制作要考虑容积、材质和形状。 1、根据应用需求选择腔体形状。几种代表性的真空腔体包括垂直真空腔体、水平真空腔体、立方真空腔体和球形真空腔体。 2、根据获得真空度选择腔体材质。钛用于极高真空&#xff1b;…

qt 移植到vs后,常见问题汇总????

1.第一次在VS中编译QT项目&#xff0c;因为在MinGW中不能编译带有qtwebengine的程序&#xff0c;因为这个引擎使用的google浏览器的内核&#xff0c;据QT官方的说法&#xff1a;google不喜欢MinGW,所以QT5.5以后的版本中带有这个模块的的部分将无法编译通过&#xff0c;我们只能…

2023年五一杯数学建模A题无人机定点投放问题求解全过程论文及程序

2023年五一杯数学建模 A题 无人机定点投放问题 原题再现&#xff1a; 随着科学技术的不断发展&#xff0c;无人机在许多领域都有着广泛的应用。对于空中执行定点投放任务的无人机&#xff0c;其投放精度不仅依赖于无人机的操作技术&#xff0c;而且还与无人机执行任务时所处状…

【C++】匿名对象 ① ( 匿名对象引入 | 匿名对象简介 | 匿名对象概念 | 匿名对象作用域 - 对象创建与销毁 )

文章目录 一、匿名对象引入二、匿名对象简介1、匿名对象概念2、匿名对象作用域 - 对象创建与销毁3、代码示例 - 创建并使用匿名对象 一、匿名对象引入 匿名对象引入 : 在上一篇博客 【C】拷贝构造函数调用时机 ② ( 对象值作为函数参数 | 对象值作为函数返回值 ) 中 , 讲到了 如…

Science adv | 转录因子SPIC连接胚胎干细胞中的细胞代谢与表观调控

代谢是生化反应网络的结果&#xff0c;这些反应吸收营养物质并对其进行处理&#xff0c;以满足细胞的需求&#xff0c;包括能量产生和生物合成。反应的中间体被用作各种表观基因组修饰酶的底物和辅助因子&#xff0c;因此代谢与表观遗传密切相关。代谢结合表观遗传涉及疾病&…

不安全的反序列化(phpjava)及漏洞复现

不安全的反序列化 1. 序列化与反序列化 A8:2017-不安全的反序列化 A08:2021-Software and Data Integrity Failures 为什么要序列化&#xff1f; 序列化&#xff0c;将对象的状态信息转换为可以存储或传输的形式的过程&#xff0c;这种形式大多为字节流、字符串、json 串。…

怎么在树莓派上搭建WordPress博客网站,并发布到外网可访问?

文章目录 序幕概述1. 安装 PHP2. 安装MySQL数据库3. 安装 Wordpress4. 设置您的 WordPress 数据库设置 MySQL/MariaDB创建 WordPress 数据库 5. WordPress configuration6. 将WordPress站点发布到公网安装相对URL插件修改config.php配置 7. 支持好友链接样式8. 定制主题 序幕 …

OpenCV(四十一):图像分割-分水岭法

1.分水岭方法介绍 OpenCV 提供了分水岭算法&#xff08;Watershed Algorithm&#xff09;的实现&#xff0c; 使用分水岭算法对图像进行分割&#xff0c;将图像的不同区域分割成互不干扰的区域。分水岭算法模拟了水在图像中的扩散和聚集过程&#xff0c;将标记的边界被看作是阻…

Edge官方鼠标手势

前言 日期&#xff1a;2023年8月 Edge浏览器目前已自带官方的鼠标手势功能&#xff0c;若要使用首先将浏览器更新至最新版&#xff0c;下文介绍使用方法。 官方鼠标手势 前提 更新Edge至最新版&#xff0c;并关闭其它鼠标手势扩展。 开启鼠标手势 打开Edge浏览器的设置&…

NoSQL之redis持久化(RDB、AOF)

目录 一、Redis高可用 二、Redis持久化 1、持久化的功能 2、Redis的两种持久化 三、RDB 持久化 1、触发条件 1.1 手动触发 1.2 自动触发 1.3 其它自动触发机制 2、执行流程 3、启动时加载RED文件(恢复) 四、Redis的AOF持久化 1、开启AOF 2、执行流程 2.1 命令追加…