「C++」类和对象(2)

news2024/12/30 3:38:23

欢迎大家来到小鸥的类和对象第二篇博客~

目录

类的默认成员函数

构造函数

构造函数的特点:

析构函数

析构函数的特点:

拷贝构造函数

拷贝构造的特点:

结语:


本篇会着重讲解类和对象中的难点:类的默认成员函数

由于篇幅原因,本篇只讲解构造,析构以及拷贝构造三个默认成员函数,运算符重载等内容将结合Date类在下一篇讲解

类的默认成员函数

默认成员函数就是指我们没有手动显示实现的函数,编译器会在实例化类的对象时自动生成这些默认成员函数。

一个类在我们不写的情况下,会自动生成6个默认成员函数(C++11以后还增加了两个默认成员函数:移动构造和移动赋值),默认成员函数重要且复杂,学习目标主要有两个:

  1. 我们不显示实现时,编译器默认生成的函数的行为是什么,确认是否满足需求;
  2. 当编译器生成的默认成员函数不满足需求时,学会显示实习这些函数。

构造函数

构造函数虽然叫构造,但它的作用并不是用来创建对象的,而当创建一个类类型的对象时,每个对象在创建完成后都要进行初始化,构造函数的作用就在于此,将创建好的实例化对象进行初始化。

构造函数的特点:

  1. 函数名和类名相同;

  2. 无返回值(区别于返回值为void的无返回值函数,构造函数连void都不用写出来,只有单独的函数名);

  3. 对象在实例化时会自动调用该类对应的构造函数;

  4. 构造函数可以重载;

  5. 若类中没有显示定义构造函数,那么C++编译器将会自动生成一个无参的构造函数,若显示定义构造函数则编译器不会生成;

  6. 无参构造函数、全缺省构造函数、编译器自动生成的构造函数都叫做默认函数,而不是单指编译器默认生成的构造函数为默认构造函数。

    三个默认 构造函数,在一个类类型中有且仅有一个,不能同时存在。且要注意,无参函数和全缺省函数调用时可能会产生歧义。

    总结起来就是:不传实参就可以调用的构造函数为默认构造函数;

  7. 编译器生成的默认构造函数为无参函数且对内置类型(说明: C++把类型分成内置类型(基本类型)和⾃定义类型。 内置类型就是语⾔提供的原⽣数据类型,如:int/char/double/指针等, ⾃定义类型就是我们使⽤class/struct等关键字⾃⼰定义的类型。)的成员变量没有硬性的初始化要求,即对内置类型是否初始化是不确定的,看编译器。而对于自定义类型的成员变量,会要求调用这个成员变量的默认构造函数来初始化。如果没有就会报错

#include <iostream>
using namespace std;
class hdmo
{
public:
	//1.无参数构造函数
	/*hdmo()
	{
		_year = 1;
		_month = 1;
		_day = 1;
	}*/
	//2.含参构造函数
	/*hdmo(int year, int month, int day)
	{
		_year = year;
		_month = month;
		_day = day;
	}*/
	//3.全缺省构造函数
	hdmo(int year = 1, int month = 1, int day = 1)
	{
		_year = year;
		_month = month;
		_day = day;
	}
	void Print()
	{
		cout << _year << '.' << _month << '.' << _day << endl;
	}
private:
	int _year;
	int _month;
	int _day;
};
int main()
{
	hdmo h1;//不传递实参时不需要加()
	//hdmo h1();//(错误的写法)函数声明还是定义对象?
	h1.Print();

	hdmo h2(2024, 3, 4);//当给构造函数传递实参时,直接在定义对象时后面加上(实参)
	h2.Print();
	return 0;
}
  • 注意点:

    • 只有在要给构造函数传递实参时才在定义对象的后面使用 (实参) 用于传递;
    • 无参数传递的时候,也不能在定义对象处加(),因为这样会和函数声明分不开,产生歧义
  • 由于编译器自动生成的构造函数对于内置类型是否初始化不确定的,所以大多数时候构造函数都是要自己实现的

析构函数

我们知道构造函数是对成员变量的初始化,那么马上来到的析构函数则是完成对象中资源的清理释放⼯作(不是销毁),在对象的生命周期结束前,会自动调用析构函数来释放需要释放的空间(比如动态申请的空间);当对象不存在需要释放的变量时,则可以不用写。

需要注意的是:像局部对象或者函数都是存在栈帧的,当栈帧销毁时,(如内置类型)就自动释放了空间了,此时是不需要用到析构函数的;需要用到的场景一般都为我们自己申请空间的情况,即需要用到free的情况。

析构函数的特点:

  1. 析构函数就是相对于构造函数在类名前面加上~
  2. 没有参数和返回值(和构造函数一样,void也不需要加)。
  3. 每个类只有一个析构函数,若未显示定义,则系统自动生成默认析构函数。
  4. 对象的生命周期结束时,自动调用
  5. 和构造函数相似,编译器自动生成的析构函数对内置类型不做处理,当存在自定义类型时,则会调用对应的析构函数。
  6. 不论是否显示定义析构函数,都会自动调用自定义类型的析构函数,没有则会报错;即便显示定义的析构函数中不包含调用自定义类型析构函数的语句,系统也会自动去调用自定义类型的析构函数防止内存泄漏,即自定义类型的析构函数,无论如何都会调用
  7. 当类中没有申请空间时,析构函数就可以不写,直接使用编译器自动生成的;但当存在空间的申请时,则必须显示定义析构函数,否则将导致内存泄漏。
  8. 当一个局部域存在多个需要析构的对象时,C++规定后定义的先析构(和数据结构中栈的先进后出相似)。
//初始化栈
#include <iostream>
using namespace std;
class stack
{
public:
	//析构函数(释放空间)
	~stack()
	{
		free(_a);
		_a = nullptr;
		_top = _capacity = 0;
	}
	//构造函数(变量初始化)
	stack(int n = 4)
	{
		_a = (int*)malloc(sizeof(int) * n);
		if (_a == nullptr)
		{
			perror("malloc fail!");
			return;
		}
		_capacity = n;
		_top = 0;
	}
private:
	int* _a;
	size_t _top;
	size_t _capacity;
};

class MyQueue
{
public:
	//自动生成构造函数,两个stack变量的初始化就会自动调用stack类中的默认构造函数,即stack(int n = 4);
	//所以MyQueue类中的构造函数就不需要手动实现了

	//自动生成的析构函数会自动调用stack类中的析构函数来释放两个stack类的变量
	~MyQueue()
	{
		;//即便显式定义时不调用stack的析构函数也不会出错,因为编译器也会自动去调用。
	}
private:
	stack pushstack;
	stack popstack;
};

拷贝构造函数

定义:如果一个构造函数的第一个参数是自身类类型的引用,且其他的所有参数都有默认值(缺省参数),则这个构造函数也叫做拷贝构造函数,即拷贝构造函数是一个特殊的构造函数。

拷贝构造的作用就是在初始化时,解决想要使用相同类型对象来初始化新对象的情况

拷贝构造的特点:

  1. 拷贝构造函数也是构造函数的一个重载函数;
  2. 拷贝构造函数的第一个参数必须为类类型对象的引用,如果使用传值调用编译器会直接报错,因为语法逻辑将导致引发无穷递归(C++中包含类对象的传值调用,拷贝数据时会先调用对象对应的拷贝构造函数)。
  3. C++规定自定义类型对象进行拷贝行为时必须调用拷贝构造函数,所以自定义类型传值传参和传值返回都会调用拷贝构造。
  4. 当没有显示定义拷贝构造,编译器会自动生成拷贝构造函数。自动生成的拷贝会对内置类型进行值拷贝(浅拷贝),自定义类型则会调用它的拷贝构造。
  5. 当一个类中只包含了内置类型,且没有指向资源时(动态内存申请),就可以不显示写出拷贝构造,编译器自动生成的拷贝构造就可以满足需求;但如果类中有自定义类型或者指向资源的内容,就需要我们显示的写出拷贝构造函数。若一个类中显示写出了析构函数并释放了资源,则它就需要显示的写出拷贝构造函数。
  6. 函数中的传值返回会产生一个临时对象调用拷贝构造,传引用返回返回的是返回对象的别名,不会产生拷贝。若返回的对象是一个当前函数局部域的一个局部对象,那么函数结束时该对象就销毁了,此时传引用返回就会出错,因为该引用所代表的对象已经销毁,此时就类似一个野指针的错误。虽然传引用返回可以减少拷贝所消耗的资源,但是前提要搞清楚返回对象的作用域。
#include <iostream>
using namespace std;
typedef int STDataType;

class stack
{
public:
	//构造函数(初始化栈)
	stack(int n = 4)
	{
		_a = (STDataType*)malloc(sizeof(int) * n);
		if (_a == nullptr)
		{
			perror("malloc fail");
			return;
		}
		_top = 0;
		_capacity = n;
	}
	//析构函数(释放动态空间)
	~stack()
	{
		free(_a);
		_a = nullptr;
		_top = 0;
		_capacity = 0;
	}
	//拷贝构造
	stack(const stack& st)
	{
		//创建一个大小相同的新栈,将原来栈的内容复制到新栈
		_a = (STDataType*)malloc(sizeof(STDataType) * st._capacity);
		if (_a == nullptr)
		{
			perror("malloc fail!");
			return;
		}
		memcpy(_a, st._a, sizeof(STDataType) * st._top);
		_top = st._top;
		_capacity = st._capacity;
	}
	void Push(STDataType x)
	{
		//判断空间是否足够
		if (_top == _capacity)
		{
			int newcapacity = _capacity * 2;
			STDataType* tmp = (STDataType*)realloc(_a, newcapacity * sizeof(STDataType));
			if (tmp == nullptr)
			{
				perror("realloc fail!");
				return;
			}
			_a = tmp;
			_capacity = newcapacity;
		}
		_a[_top++] = x;
	}
private:
	STDataType* _a;
	int _top;
	int _capacity;
};
//两个栈实现队列
class MyQueue
{
public:
	//
private:
	stack pushst;
	stack popst;
};

int main()
{
	stack st1;
	st1.Push(1);
	st1.Push(2);
	//stack st2 = st1;
	stack st2(st1);//调用拷贝构造

	MyQueue mq1;
	//MyQueue中自动生成的拷贝构造会自动调用stack的拷贝构造
	MyQueue mq2 = mq1;

	return 0;
}

结语:

本篇的讲解就到这里,有不足的地方请大家指正,互相成长,下一篇将结合Date类实现运算符重载内容,欢迎再次到来~

个人主页:海盗猫鸥-CSDN博客

本期专栏:C++_海盗猫鸥的博客-CSDN博客

感谢大家关注~

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

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

相关文章

Ubuntu环境的MySql下载安装

下载压缩包 此文章下载的mysql版本位5.7.29 sudo wget https://downloads.mysql.com/archives/get/p/23/file/mysql-server_5.7.29-1ubuntu18.04_amd64.deb-bundle.tar解压缩 sudo tar -xvf mysql-server_5.7.29-1ubuntu18.04_amd64.deb-bundle.tar命令解释 -x&#xff1a;…

鸿蒙Next-拉起支付宝的三种方式——教程

鸿蒙Next-拉起支付宝的三种方式——教程 鸿蒙Next系统即将上线&#xff0c;应用市场逐渐丰富、很多APP都准备接入支付宝做支付功能&#xff0c;目前来说有三种方式拉起支付宝&#xff1a;通过支付宝SDK拉起、使用OpenLink拉起、传入支付宝包名使用startAbility拉起。以上的三种…

走心机做不锈钢哪个牌子好

不锈钢是现代生活中不可或缺的材料&#xff0c;它广泛应用于厨房用具、家具、建筑等领域。在市场上&#xff0c;有许多不锈钢需要加工零件供消费者选择&#xff0c;那么在选择不锈钢加工零件时制品时&#xff0c;应该如何选择数控走心机&#xff0c;找到最好的品牌呢&#xff1…

CodeSys中动态切换3D模型

文章目录 需求研究结果 需求 在前面的【CodeSys开发3d机械臂显示控件】中&#xff0c;我们已经实现了一个可以显示3d模型的控件。但是这个控件是和使用的3d模型绑定死的&#xff0c;在安装这个控件时就已经将模型文件于控件一起安装到codesys中。 假如我想在不同的工程中&…

Numpy中type()、ndim、shape、size、dtype、astype的用法

目录 numpy基础介绍示例分析及总结&#xff1a;itemsize、nbytes函数 numpy基础介绍 Numpy 补充了Python语言所欠缺的数值计算能力,是其它数据分析及机器学习库的底层库。因其完全标准C语言实现&#xff0c;运行效率充分优化。最重要一点是开源免费。numpy的核心是矩阵&#x…

思维导图怎么画好看又简单?5个软件帮助你快速进行思维导图绘制

思维导图怎么画好看又简单&#xff1f;5个软件帮助你快速进行思维导图绘制 思维导图是一种有效的思维整理和展示工具&#xff0c;可以帮助你将复杂的想法进行可视化&#xff0c;提升工作和学习效率。为了让思维导图既好看又简单&#xff0c;选择合适的软件能够大大提高绘制效率…

UE中Camera Clip截面修改

UE中Camera无法修改远截面&#xff08;FarClipingPlane)&#xff0c;只可修改近截面&#xff08;NearClipingPlane&#xff09;&#xff1a; 至于为什么无法修改远截面&#xff0c;看下代码&#xff0c;尝试继承UE的CameraComponent打印出相机投影矩阵&#xff1a; #include …

python编程知识(实现数据加密和解密)

&#x1f468;‍&#x1f4bb;个人主页&#xff1a;开发者-曼亿点 &#x1f468;‍&#x1f4bb; hallo 欢迎 点赞&#x1f44d; 收藏⭐ 留言&#x1f4dd; 加关注✅! &#x1f468;‍&#x1f4bb; 本文由 曼亿点 原创 &#x1f468;‍&#x1f4bb; 收录于专栏&#xff1a…

在模板中使用 Django 会话

在 Django 中使用会话&#xff08;session&#xff09;可以让你在用户访问网站的过程中存储和访问临时数据。我们可以利用会话在速度计算器的例子中存储和显示上次计算的结果。 1、问题背景 在 Django 中&#xff0c;可以使用会话来存储用户数据。在某些情况下&#xff0c;我们…

双绞线如何抑制传导干扰

一&#xff0e;案例简介 产品去做CE认证时&#xff0c;被告知传导抗扰未通过&#xff0c;网络会断连。 剖开网线外皮&#xff0c;发现内部是散装的&#xff0c;非双绞线。因此换成双绞线网线&#xff0c;复测&#xff0c;传导抗扰通过了。 图1 非双绞线和双绞线示意图 为什么…

经销商数据对接方案:借助轻易云数据集成平台实现高效互联

在现在很多品牌方的实际需求中&#xff0c;品牌商与经销商之间的渠道博弈日益激烈。品牌商渴望掌握经销商的销量和库存数据&#xff0c;以便更好地规划生产和库存&#xff0c;提升品牌影响力&#xff1b;经销商则期望在避免库存积压的同时抢占市场&#xff0c;加速资金周转以获…

活动预告|“AI+Security”系列第3期:AI安全智能体,重塑安全团队工作范式

由安全极客、Wisemodel社区、InForSec网络安全研究国际学术论坛和海升集团联合主办的 “AISecurity”系列第3期&#xff1a; AI 安全智能体&#xff0c;重塑安全团队工作范式 线下活动 将于2024年9月11日下午14:00 在中关村智造大街G座路演厅 正式举行 欢迎扫描海报中二…

Javaweb(前端)

目录 Web开发 Web前端 HTMLCSS 盒子模型 JavaScript js引入方式 js基础语法 js函数 js对象&#xff08;JSONBOMDOM&#xff09; js事件监听 Vue ​编辑Vue快速入门 Vue常用指令 Vue生命周期 Ajax 原生Ajax Axios YApi&#xff08;应用网页&#xff09; 前端工程…

打造一流的研发型企业--- 金发科技研发驱动力初探

2006年3月29日&#xff0c;国家发改委副主任欧新黔亲自为金发科技颁发了“中国改性塑料行业第一位”、“中国合成材料制造业十强”、“中国石油化工全行业百强”三块铜牌证书&#xff0c;金发科技终于成为名符其实的行业“老大”。公司产品销售额增长迅速&#xff0c; 2006年完…

Java健康养老智慧相伴养老护理小程序系统源码代办陪诊陪护更安心

健康养老&#xff0c;智慧相伴 —— 养老护理小程序&#xff0c;代办陪诊陪护更安心 &#x1f308;【开篇&#xff1a;智慧养老&#xff0c;新时代的温馨守护】&#x1f308; 在这个快节奏的时代&#xff0c;我们总希望能给予家人更多的关爱与陪伴&#xff0c;尤其是家中的长…

【AIGC赋能】短视频创作新纪元:一键生成,爆款不再难!

文章目录 一、AI技术的深度融入&#xff1a;从辅助到主导二、实际应用场景&#xff1a;覆盖创作全流程三、展望未来&#xff1a;AI短视频创作的无限可能 《AI短视频生成与剪辑实战108招&#xff1a;ChatGPT剪映》编辑推荐内容简介作者简介目录前言/序言内页插图 在数字化浪潮的…

IP地址是怎么实现HTTPS访问的?

首先&#xff0c;需要明确的是&#xff0c;IP地址&#xff08;Internet Protocol Address&#xff09;是互联网上设备&#xff08;如服务器、路由器等&#xff09;的唯一标识符&#xff0c;它允许数据包在网络中正确地路由和传输。然而&#xff0c;IP地址本身并不直接支持HTTPS…

cesium可不可以改变影像底图颜色,如何给地球底图影像添加一层滤镜蒙版?

废话&#xff1a;你的球是不是很丑&#xff1f;是不是没有科技感&#xff1f;是不是没有好看的影像&#xff1f; 因果&#xff1a; 因&#xff1a;客户问&#xff0c;底图可不可以改变颜色&#xff0c;想让球更漂亮一些。 答&#xff1a;可以改变影像饱和度&#xff0c;透明度…

【MATLAB源码-第164期】基于matlab的轴承故障三种谱图:细化谱,功率谱,倒谱对比分析仿真。

操作环境&#xff1a; MATLAB 2022a 1、算法描述 轴承故障分析是一种重要的维护和监控手段&#xff0c;能够帮助工程师及时发现和解决轴承在运行中可能遇到的各种问题。在轴承故障诊断中&#xff0c;通常会使用到三种谱图分析方法&#xff1a;细化谱&#xff08;Fine Spectr…

基于大数据的电商平台电脑销售数据分析系统

温馨提示&#xff1a;文末有 CSDN 平台官方提供的学长 QQ 名片 :) 1. 项目简介 随着电子商务的蓬勃发展&#xff0c;各大电商平台积累了海量的商品数据。如何从这些数据中提取有价值的信息&#xff0c;对于商家来说至关重要。本项目利用网络爬虫技术从京东电商平台采集各类品牌…