Cpp学习——类与对象(2)

news2024/11/15 19:28:39

思维导图:

一,构造函数

1.定义

对于构造函数首先就要知道构造函数怎么写,构造函数怎么写呢?你要知道如下两点:

1.构造函数的函数名要与类名相同

2.构造函数是没有返回值的,但可以有参数。

因为这第二点,所以构造函数便可以被重载变成许多的具有不同种类的构造函数。

2.构造函数的分类

1.系统生成的默认构造参数

首先写一个日期类:

class Date
{
public:
	

private:
	int _year;
	int _month;
	int _day;
};

这里可以看到的是日期类里面的每一个变量都没有被赋值,但是在调用实例化一个类以后这些变量会被赋值吗?看看便知道了:

可以看到这些变量都被附上了一个相同的随机值。这是因为调用了系统生成的默认构造函数的原因。如果没有调用默认的构造参数的话就会是这个样子:

2.不含参的构造函数

 其实我们也可以自己定义一个不含参的构造函数来达到和系统调用的默认参数一样的效果:

这里需要注意一下,要调用构造无参的构造函数时不能在实例化对象的后面加一个()这样会和声明一个函数的意思混淆。 

3.含参的构造参数

 可以看到上面两种构造函数都没有将类里面的变量初始化为我们想要的值的作用,但是含参的构造函数却有这个作用:

需要注意的是,当我们自己写了一个自定义的构造函数的时候系统便不会再生成一个无参的构造函数。所以当我们再次想要Date d2,就会报错。在这里,又因为我们学习过缺省参数的概念,所以我们可以在定义含参的构造参数时决定定义的构造参数是全缺省的还是半缺省的。

全缺省:

在这里又可以看到,在我们定义了一个全缺省的构造函数以后便可以不传参的实例化一个对象。 

 半缺省:

在这里可以看到在我们定义一个半缺省的构造函数以后是不能够不传参实例化一个对象的。 

4,默认构造函数 

你是不是以为默认构造函数只有一种,那就是系统自动生成的默认构造函数?但是,其实默认构造函数在Cpp中的意思是不用传参便可以调用的函数。所以,其实在Cpp中默认构造函数有三种:

1.系统自动生成的默认构造函数。

2.不含参的自定义构造函数。

3.全缺省的构造函数。

这三种构造函数在Cpp中都被叫做默认构造函数。这样搞确实是挺坑的。所以为了填坑,我们的Cpp祖师爷便规定可以给成员变量赋值从而达到即使不定义构造函数我们也能初始化的效果:

 这样便可以给当初定义默认构造函数时的缺陷打上一点补丁了。

二,析构函数

1.定义

 析构函数可以说是构造函数的一个重载形式了。要定义析构函数要知道以下几点:

1.析构函数的前面有~,后面接的名字和类名相同。

2.析构函数没有返回值。

3.析构函数不含参数,所以不会构成重载,因而每一个类都有自己唯一的一个构造函数。

 2.析构函数的作用

在上面的日期类里面写一个构造函数:

class Date
{
public:
	Date(int year = 1999,int month = 9 ,int day = 6 )
	{
		_year = year;
		_month = month;
		_day = day;
	}

  //构造函数
	~Date()
	{
		_year = 0;
		_month = 0;
		_day = 0;
	}
private:
	int _year;
	int _month;
	int _day ;
};

int main()
{
	Date d1;
	return 0;
}

其实你会发现这并没有什么用,因为即使你不调用构造函数这些临时的变量也会自动的销毁。所以这也体现了析构函数只会在清理资源时发挥它的作用。比如在我们调用一个堆上生成的变量时,便可以调用析构函数。如:

class Stack
{
public:
	Stack(int n = 4)//构造函数
	{
		int* tmp = (int*)malloc(sizeof(int) * n);
		if (tmp == NULL)
		{
			perror("malloc fail\n");
			return;
		}
		a = tmp;

		top = n;
		size = n;
	}

	~Stack()//析构函数释放资源
	{
		free(a);
		top = 0;
		size = 0;
	}

private:
	int* a;
	int top;
	int size;
};

int main()
{
	Stack ST(1000);
	return 0;
}

这样便可以在定义了一个栈以后避免忘记手动销毁而造成内存泄漏的问题。因为析构函数是会被自动调用的。 

三,拷贝构造

 1.拷贝构造的定义

拷贝钩爪可以说是构造函数的另外一种重载形式了。拷贝构造的特点有下面几点:

1.函数名和类名相同

2.拷贝构造的参数中必须有一个自定义的类类型的参数

3.拷贝构造不能传值,否则会发生无穷递归的问题。同时也是为了提高程序的效率。

2. 为什么要有拷贝构造

拷贝构造其实是一种深拷贝,而我们平时的拷贝方式就是一种浅拷贝方式。因为是浅拷贝所以在我们拷贝一些指针时便会将指针的地址一摸一样的拷贝过来。此时因为我们有一个析构函数并且析构函数是自动调用的所以对同一个指针所指向的内存空间便会被置空两次因而导致报错,如:

class Stack
{
public:
	Stack(int n = 4)
	{
		int* tmp = (int*)malloc(sizeof(int) * n);
		if (tmp == NULL)
		{
			perror("malloc fail\n");
			return;
		}
		a = tmp;

		top = n;
		size = n;
	}

	~Stack()
	{
		cout << "~Stack()" << endl;//调用一次析构函数便打印一次~Stack
		free(a);
        a = NULL;
		top = 0;
		size = 0;
	}

private:
	int* a;
	int top;
	int size;
};

int main()
{
	Stack ST1;
	Stack ST2 = ST1;
	return 0;
}

执行结果如下:

于是这里便调用了两次的析构函数。并且:

两个不同的栈里面的指针变量a指向的都是同一块地址,所以调用两次析构函数便会对同一块地址释放两次导致错误。 因为这个原因我们便要有深拷贝让两者的指针变量的地址指向不同的两块空间。

2.拷贝构造函数的使用

 拷贝构造函数的使用首先就要弄清楚应该传什么,这里要明确的是传参数的时候我们应该传的是同类类型的引用参数。传引用参数才不会导致无限递归调用拷贝构造。所以拷贝构造的代码如下:

class Stack
{
public:
	Stack(int n = 4)
	{
		int* tmp = (int*)malloc(sizeof(int) * n);
		if (tmp == NULL)
		{
			perror("malloc fail\n");
			return;
		}
		a = tmp;

		top = n;
		size = n;
	}
	Stack(const Stack& st)//拷贝构造
	{
		a = (int*)malloc(sizeof(int) * st.size);
		size = st.size;
		top = st.top;
	}

	~Stack()
	{
		cout << "~Stack()" << endl;
		free(a);
		a = NULL;
		top = 0;
		size = 0;
	}

private:
	int* a;
	int top;
	int size;
};

int main()
{
	Stack ST1;
	Stack ST2 = ST1;
	return 0;
}

使用拷贝构造以后便可以避免两次析构同一块空间的问题:

两个类的指针也是指向不同的地址:

 完美解决!!!

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

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

相关文章

ubuntu目录分析

在Ubuntu根目录下&#xff0c;以下是一些常见文件夹的含义&#xff1a; /bin&#xff1a;存放可执行文件&#xff0c;包含一些基本的命令和工具。 /boot&#xff1a;存放启动时所需的文件&#xff0c;如内核和引导加载程序。 /dev&#xff1a;包含设备文件&#xff0c;用于与硬…

关于计算机视觉的Open3D简介

一、说明 Open3D 是一个开源库&#xff0c;使开发人员能够处理 3D 数据。它提供了一组用于 3D 数据处理、可视化和机器学习任务的工具。该库支持各种数据格式&#xff0c;例如 .ply、.obj、.stl 和 .xyz&#xff0c;并允许用户创建自定义数据结构并在程序中访问它们。 Open3D 广…

【雕爷学编程】MicroPython动手做(16)——掌控板之图片图像显示

知识点&#xff1a;什么是掌控板&#xff1f; 掌控板是一块普及STEAM创客教育、人工智能教育、机器人编程教育的开源智能硬件。它集成ESP-32高性能双核芯片&#xff0c;支持WiFi和蓝牙双模通信&#xff0c;可作为物联网节点&#xff0c;实现物联网应用。同时掌控板上集成了OLED…

进程_PCB 的理解

目录 一. PCB 的概念 1. 为什么需要PCB 2. PCB的属性 二. task struct 1. task struct 介绍 2. 查看进程指令 3. PID 4. PPID 父进程是什么&#xff1f; 为什么要有父进程&#xff1f; 5. fork 创建子进程 1) fork 后的现象 为什么会打印两次&#xff1f; 2) 的返…

用C语言实现插入排序算法

1.设计思路 用插入排序对长度为n的待排序数组A进行排序的伪代码&#xff08;在代码中&#xff0c;A中元素的数目n用A.length来表示&#xff09;。 伪代码如下&#xff1a; INSERTION-SORT(A) for j2 to A.length:keyA[j] //将A[j]插入已排序序列A[1..j-1]ij-1while i>0…

【MTI 6.S081 Lab】Copy-on-write

【MTI 6.S081 Lab】Copy-on-write The problemThe solutionImplement copy-on-write fork (hard)实验任务Hints解决方案问题解决思考uvmcopykfreekallockpagerefcow_handlertrap 虚拟内存提供了一定程度的间接性&#xff1a;内核可以通过将PTE标记为无效或只读来拦截内存引用&a…

Quartz项目搭建与任务执行源码分析

数据库准备 准备一个MySQL数据库&#xff0c;版本为8.0&#xff0c;然后创建一个库&#xff0c;并从quartz官方的版本包中找到名称为tables_mysql_innodb.sql的脚本执行进去&#xff08;脚本内容文后也有提供&#xff09;。 项目依赖说明 创建一个Maven项目&#xff0c;引入…

Python方式实现简易弹道计算机

1 问题 本周无意间刷到了德国豹2A5坦克的火控介绍&#xff0c;想自己编写一个不考虑空气阻力以及测风影响的简易弹道计算机&#xff08;大口径火炮&#xff09;。 2 方法 由高中物理知识了解到&#xff0c;炮弹出膛之后基本就是抛物线列个抛物线方程就好了; 百度得火炮的弹道方…

【Django学习】(十六)session_token认证过程与区别_响应定制

一、认识session与token 这里就直接引用别人的文章&#xff0c;不做过多说明 网络应用中session和token本质是一样的吗&#xff0c;有什么区别&#xff1f; - 知乎 二、token响应定制 在全局配置表中配置 DEFAULT_AUTHENTICATION_CLASSES: [# 指定jwt Token认证rest_framew…

python_day17_多线程

threading模块 import timedef sing():while True:print("唱歌~~~~~~~~~~~~")time.sleep(1)def dance():while True:print("跳舞############")time.sleep(1) if __name__ __main__:sing()dance()此时为单线程 import threading import timedef sing(…

Java 异常处理的使用和思考

概念 异常处理的概念起源于早期的编程语言&#xff0c;如 LISP、PL/I 和 CLU。这些编程语言首次引入了异常处理机制&#xff0c;以便在程序执行过程中检测和处理错误情况。异常处理机制随后在 Ada、Modula-3、C、Python、Java 等编程语言中得到了广泛采用和发展。在 Java 中&a…

迁移学习《Efficient and Robust Pseudo-Labeling for Unsupervised Domain Adaptation》

1 摘要 问题&#xff1a;无监督域适应传统方法将超过一定置信度阈值的数据视为目标域的伪标记数据&#xff0c;因此选择合适的阈值会影响目标性能。 在本文中&#xff0c;提出了一种新的基于置信度的加权方案来获得伪标签&#xff0c;并提出了一种自适应阈值调整策略&#xff0…

oCPC实践录 | oCPC下机制设计变得毫无意义?(2)无声的战争

接上回oCPC实践录 | oCPC下机制设计变得毫无意义&#xff1f;&#xff08;1&#xff09;事出异常必有妖&#xff0c;互联网广告最开始采用的广义第一价格密封拍卖&#xff08;GFP)&#xff0c;对广告主而言&#xff0c;需要不断感知竞争对手的变化&#xff0c;修改报价&#xf…

text-generation-webui加载chatglm2-6b时,报错,要求set the option trust_remote_code=True

背景 使用text-generation-webui加载chatglm2-6b大模型时报错&#xff0c;要求设置option trust_remote_codeTrue&#xff0c;一开始没注意界面&#xff0c;去翻找配置文件&#xff0c;后来发现&#xff0c;就在Model界面&#xff0c;有一个复选框&#xff0c;可以进行设置&am…

IO模型epoll

通过epoll实现一个并发服务器 服务器 #include <stdio.h> #include <string.h> #include <stdlib.h> #include <sys/types.h> #include <sys/socket.h> #include <netinet/in.h> #include <netinet/ip.h> #include <arpa/inet.h…

【新星计划】STM32F103C8T6 - C语言 - 蓝牙JDY-31-SPP串口通信实验

文章目录 蓝牙技术的发展历史SPP蓝牙串口BLE协议&#xff08;超低功耗应用蓝牙协议&#xff09; 常见通用蓝牙模块JDY-31-SPPHC05/06 Keil 工程开发模版main.c 源文件&#xff1a;接线方式&#xff1a;烧录工具&#xff1a;FlyMcu串口调试工具&#xff1a;XCOM蓝牙调试助手APP …

Yolov8训练自己的数据集合(最新实验数据)

一、安装环境 笔者环境如下&#xff1a; win10 anaconda python3.8二、clone代码 地址如下&#xff0c;可以直接使用git命令进行clone,也可以直接去网站下载 git clone https://github.com/ultralytics/ultralytics代码目录如下所示 三、安装必要的库 其实这里比较重要的是…

java的instanceof操作符

说明 java的instanceof操作符可以用于类型的比较或者模式匹配比较。instanceof关键字左边是对象的引用&#xff0c;右边是引用类型或者模式。 如果instanceof关键字右边是一个引用类型&#xff0c;那么instanceof关键字是一个类型比较操作符。 如果instanceof关键字右边是一个…

6.事件监听(绑定)

6.1事件监听 ●什么是事件? 事件是在编程时系统内发生的动作或者发生的事情 比如用户在网页上单击一个按钮 ●什么是事件监听? 就是让程序检测是否有事件产生&#xff0c;一旦有事件触发&#xff0c;就立即调用一个函数做出响应&#xff0c;也称为绑定事件或者注册事件&…

FL Studio 21官方中文版功能介绍及2023最新下载详细图文安装激活教程。FL Studio 21需要系统配置要求

FL Studio 21版本更新现已发布&#xff0c;在这次更新中优化了很多功能&#xff0c;但这些现在都不重要&#xff0c;FL Studio21版本的这次更新中令人瞩目的更新莫过于对简体中文版的支持了。以前FL Studio只有英文版&#xff0c;想要用上中文版只有用汉化包&#xff0c;而且有…