C++:类和对象(3)

news2024/9/22 21:18:22

目录

1.构造函数调用规则

2.深拷贝和浅拷贝

3.初始化列表

4.类对象作为类成员


1.构造函数调用规则

     默认情况下,C++编译器至少给类添加三个函数:

1.默认构造函数(无参,函数体为空)
2.默认析构函数(无参,函数体为空)
3.默认拷贝构造函数,对属性进行值的拷贝

     构造函数调用规则如下:

如果用户自己实现了有参构造函数,C++不会再提供无参构造函数,但是会提供默认拷贝构造

如果用户自己实现了拷贝构造函数,C++不会提供任何构造函数

     比如:

     1.如果用户自己实构造函数,C++不会再提供无参构造函数,但是会提供默认拷贝构造

#include<iostream>
using namespace std;
class Person
{
public:
	//有参构造函数
	Person(int age)
	{
		_age = age;
		cout << "有参构造函数调用" << endl;
	}
	//析构函数
	~Person()
	{
		cout << "析构函数调用" << endl;
	}
	//拷贝构造函数
	Person(const Person& p)
	{
		_age = p._age;
		cout << "拷贝构造函数调用" << endl;
	}

	int _age;

};
int main()
{
	Person p;
	p._age = 18;

	Person p2(p);

	cout << "p2的年龄为:" << p2._age << endl;

	return 0;
}

     此时会显示报错:

类 "Person" 不存在默认构造函数

     因为我们写下了Person p,没有参数,要调用系统或者用户提供的无参构造函数,但因为我们实现了有参构造函数,系统就不会提供无参构造函数,同时我们自己也没有实现无参构造函数,就会报错。

      还是会提供默认构造,如果我们把Person p和拷贝构造函数代码删掉:

#include<iostream>
using namespace std;
class Person
{
public:
	//有参构造函数
	Person(int age)
	{
		_age = age;
		cout << "有参构造函数调用" << endl;
	}
	//析构函数
	~Person()
	{
		cout << "析构函数调用" << endl;
	}

	int _age;

};
int main()
{
	
    Person p(18);

	Person p2(p);

	cout << "p2的年龄为:" << p2._age << endl;

	return 0;
}

     运行结果:

有参构造函数调用
p2的年龄为:18
析构函数调用
析构函数调用

      可以看到,系统会提供默认拷贝构造

2.如果用户自己实现了拷贝构造函数,C++不会提供任何构造函数

#include<iostream>
using namespace std;
class Person
{
public:
	//拷贝构造函数
	Person(const Person& p)
	{
		_age = p._age;
		cout << "拷贝构造函数调用" << endl;
	}
	//析构函数
	~Person()
	{
		cout << "析构函数调用" << endl;
	}
	

	int _age;

};
int main()
{
	Person p;

	return 0;
}

     报错:

“Person”: 没有合适的默认构造函数可用

     可以看出,当我们自己实现了拷贝构造函数,如果我们自己不实现无参构造函数,系统就不会提供,有参构造函数系统本来就提供不了。

2.深拷贝和浅拷贝

     浅拷贝:简单的赋值拷贝操作

     深拷贝:在堆区重新申请空间,进行拷贝操作

#include<iostream>
using namespace std;
class Person
{
public:
	//无参构造函数
	Person()
	{
		cout << "无参构造函数" << endl;
	}
	//有参构造函数
	Person(int age,int height)
	{
		_age = age;
		_height=new int(height);
		cout << "有参构造函数调用" << endl;
	}
	//析构函数
	~Person()
	{
		//将堆区开辟的数据做释放操作
		if (_height != NULL)
		{
			delete _height;
			_height = NULL;
		}
		cout << "析构函数调用" << endl;
	}

	int _age;
	int* _height;
};
int main()
{
	Person p1(18,180);

	cout << "p1的年龄为:" << p1._age <<"身高为:"<<*p1._height<<endl;

	Person p2(p1);

	cout << "p2的年龄为:" << p2._age <<"身高为:"<<*p2._height<<endl;


	return 0;
}

     我们想把身高这个数据开辟在堆区,就可以用new语法来创建,new创建之后返回一个指向该空间的指针,用_height来接收,同时堆区开辟的空间需要我们程序员手动来释放,上面给出了代码,运行看看怎么样,不好,出错了,这时候会出现报错:

已在 Project15.exe 中执行断点指令(__debugbreak()语句或类似调用)。

     这是为什么呢?其实是因为我们利用编译器提供的拷贝构造函数,做的是浅拷贝的操作

     p1和p2的指针都指向同一块空间,同一块空间释放两次肯定是不允许的,所以报错意料之中,浅拷贝带来的问题就是堆区的内存重复释放,要用深拷贝来解决

#include<iostream>
using namespace std;
class Person
{
public:
	//无参构造函数
	Person()
	{
		cout << "无参构造函数" << endl;
	}
	//有参构造函数
	Person(int age,int height)
	{
		_age = age;
		_height=new int(height);
		cout << "有参构造函数调用" << endl;
	}
	//自己实现拷贝构造函数,解决浅拷贝问题
	Person(const Person& p)
	{
		_age = p._age;
        //_height=p._height;编译器提供的拷贝构造函数实现这段代码,就是直接赋值
		_height = new int(*p._height);
        cout<<"拷贝构造函数调用"<<endl;
	}
	//析构函数
	~Person()
	{
		//将堆区开辟的数据做释放操作
		if (_height != NULL)
		{
			delete _height;
			_height = NULL;
		}
		cout << "析构函数调用" << endl;
	}

	int _age;
	int* _height;
};
int main()
{
	Person p1(18,180);

	cout << "p1的年龄为:" << p1._age <<"身高为:"<<*p1._height<<endl;

	Person p2(p1);

	cout << "p2的年龄为:" << p2._age <<"身高为:"<<*p2._height<<endl;


	return 0;
}

     自己再开辟一块堆区空间,将指针指向这块空间,释放的时候就不会再重复释放空间了。

3.初始化列表

     初始化列表语法用来初始化属性

语法:构造函数():属性1(值1),属性2(值2)...{}

     示例:

     传统的初始化操作:

class Person
{
public:
	Person(int a, int b, int c)
	{
		_a = a;
		_b = b;
		_c = c;
	}
	int _a;
	int _b;
	int _c;
};

     初始化列表操作:

#include<iostream>
using namespace std;
class Person
{
public:
	Person(int a, int b, int c):_a(a),_b(b),_c(c)
	{

	}
	int _a;
	int _b;
	int _c;
};
int main()
{
	Person p(10, 20, 30);
	cout << "_a=" << p._a << endl;
	cout << "_b=" << p._b << endl;
	cout << "_c=" << p._c << endl;
	
	return 0;
}

     输出:

_a=10
_b=20
_c=30

     使用初始化列表,函数体就可以写其他的内容,很灵活。

4.类对象作为类成员

    C++中类的成员可以是另一个类的对象,这种成员叫对象成员   

    比如:

class A{};
class B
{
   A a;
};

     那我们就有问题了,当我们创建B的对象时,A和B的构造函数和析构函数先执行谁的呢?让我们一起来看看

#include<iostream>
using namespace std;
class Phone
{
public:
	Phone(string Pname)
	{
		_Pname = Pname;
		cout << "Phone的构造函数调用" << endl;
	}
	~Phone()
	{
		cout << "Phone的析构函数调用" << endl;
	}
	string _Pname;
};
class Person
{
public:
	Person(string name, string Pname):_name(name),_Phone(Pname)
	{
		cout << "Person的构造函数调用" << endl;
	}
	~Person()
	{
		cout << "Person的析构函数调用" << endl;
	}
	string _name;//姓名
	Phone _Phone;//手机
};
int main()
{
	Person p("张三", "华为Mate60pro");
	cout << p._name << "拿着" << p._Phone._Pname << endl;
	return 0;
}

      输出:

Phone的构造函数调用
Person的构造函数调用
张三拿着华为Mate60pro
Person的析构函数调用
Phone的析构函数调用

     可以看到,当其他对象作为本类对象时,构造时先构造其他对象,再构造本类对象;析构的顺序是先调用本类对象的析构函数,再调用其他对象的析构函数。

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

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

相关文章

GNSS位移监测站对尾矿库坝体表面位移进行自动化监测

表面位移监测&#xff1a;通过GNSS位移监测站对尾矿库坝体表面位移进行自动化监测&#xff0c;掌握尾矿坝整体表面位置的变化及其变化速率&#xff08;包括平面位移和垂直沉降&#xff09;&#xff0c;确定尾矿坝坝体整体位移变形的情况&#xff0c;是确定尾矿库安全性的重要指…

一文讲透SPSS相关性分析结果怎么看?

推荐采用《SPSS统计分析入门与应用精解&#xff08;视频教学版&#xff09;》 杨维忠、张甜 清华大学出版社“5.1 双变量相关分析” 的解答。 本节内容选自《SPSS统计分析入门与应用精解&#xff08;视频教学版&#xff09;》 杨维忠、张甜 清华大学出版社“5.1 双变量相关分析…

Protobuf 编码结构

编码结构 什么是protobuf protocol buffers 是一种语言无关、平台无关、可扩展的序列化结构数据的方法&#xff0c;可用于数据通信协议和数据存储等&#xff0c;它是 Google 提供的一个具有高效协议数据交换格式工具库&#xff0c;是一种灵活、高效和自动化机制的结构数据序列…

24款奔驰C260L升级C63包围 渣男的外表

今天店里来了一台24款奔驰C260L 一提车就过来升级 我们公司还有包上牌服务 车主说 升级完包围 帮忙安排一下 原车的包围 没有那么霸气 特别是后杠 光溜溜的 升级后 四出尾喉 尾翼 直接牌面就起来了&#xff0c;星骏汇小许Xjh15863

真核微生物基因序列鉴定工具EukRep工具的安装和详细使用方法

介绍 EukRep是一种用于鉴定并分析环境中的真核微生物的工具。它基于16S rRNA基因序列&#xff0c;可以帮助研究人员确定和分类环境样品中存在的真核微生物群落。 EukRep 从宏基因组数据集中分类真核和原核序列 安装 要求Python3 推荐使用conda安装&#xff1a; $ conda cre…

HUAWEI华为荣耀MagicBook X 15酷睿i5-10210U处理器集显(BBR-WAH9)笔记本电脑原装出厂Windows10系统

链接&#xff1a;https://pan.baidu.com/s/1YVcnOP5YKfFOoLt0z706rg?pwdfwp0 提取码&#xff1a;fwp0 MagicBook荣耀原厂Win10系统自带所有驱动、出厂主题壁纸、系统属性专属LOGO标志、Office办公软件、华为/荣耀电脑管家等预装程序 文件格式&#xff1a;esd/wim/swm 安装…

【项目实战】分布式计算和通信框架(AKKA)入门介绍

一、AKKA是什么&#xff1f; Akka是一个用于构建高并发、分布式、可容错、事件驱动的应用程序的工具包和运行时。它基于Actor模型&#xff0c;提供了一种高效的并发编程模型&#xff0c;可以轻松地编写出高并发、分布式、可容错的应用程序。Akka还提供了一些常用的组件&#xf…

DMX512输出协议详解

目录 ​编辑 1、DMX512协议简介 2、DMX512协议分析 DMX512指令帧介绍 DMX512信息包 3、DMX512接口电路 4、参考代码 1、DMX512协议简介 DMX512是一种用于舞台灯光控制的数字传输协议。它是由美国舞台灯光协会&#xff08;USITT&#xff09;于1990年发布的工业标准&…

利用小红书笔记详情API:为内容运营提供强大的支持

利用小红书笔记详情API&#xff0c;内容运营者可以获得对小红书平台上的笔记内容的深入洞察&#xff0c;从而为其运营工作提供强大的支持。以下是该API如何支持内容运营的几个关键方面&#xff1a; 获取笔记内容与数据&#xff1a; API允许内容运营者直接获取小红书平台上的笔记…

Python轴承故障诊断 (九)基于VMD+CNN-BiLSTM的故障分类

往期精彩内容&#xff1a; Python-凯斯西储大学&#xff08;CWRU&#xff09;轴承数据解读与分类处理 Python轴承故障诊断 (一)短时傅里叶变换STFT Python轴承故障诊断 (二)连续小波变换CWT_pyts 小波变换 故障-CSDN博客 Python轴承故障诊断 (三)经验模态分解EMD_轴承诊断 …

57.6K star!一个免费开源的 API 开发生态系统

&#xff01;&#xff01;&#xff01;文末有链接&#xff01;&#xff01;&#xff01; 小伙伴们&#xff0c;你们有没有遇到这样的问题呢&#xff1f;当你作为前端开发者和后端开发者一起协同工作时&#xff0c;联调接口成了必须要做的工作。 而为了验证接口的稳定性和安全…

Python武器库开发-武器库篇之子域名扫描器开发(四十一)

Python武器库开发-武器库篇之子域名扫描器开发(四十一) 在我们做红队攻防或者渗透测试的过程中&#xff0c;信息收集往往都是第一步的&#xff0c;有人说&#xff1a;渗透的本质就是信息收集&#xff0c;前期好的信息收集很大程度上决定了渗透的质量和攻击面&#xff0c;本文将…

LabVIEW在高级结构监测中的创新应用

LabVIEW在高级结构监测中的创新应用 LabVIEW作为一个强大的系统设计平台&#xff0c;其在基于BOTDA&#xff08;光时域反射分析&#xff09;技术的结构监测中发挥着核心作用。利用LabVIEW的高效数据处理能力和友好的用户界面&#xff0c;开发了一个先进的监测系统。该系统专门…

ThreadPoolExecutor中的keepAliveTime详解

一.keepAliveTime的概念&#xff1a; keepAliveTime的单位是纳秒&#xff0c;即1s1000000000ns&#xff0c;1秒等于10亿纳秒。 keepAliveTime是线程池中空闲线程等待工作的超时时间。 当线程池中线程数量大于corePoolSize&#xff08;核心线程数量&#xff09;或设置了allowCor…

反诈宣传进社区 安全防护零距离

反诈宣传进社区 安全防护零距离 广州党建引领城中村治理志愿服务项目之“我爱我家”助建幸福网格项目&#xff0c;由中共广州市委政法委员会、广州市精神文明建设委员会办公室、广州市民政局广州市文化电旅游局、广州市来穗人员服务管理局、广州市消防救援支队、共青团广州市委…

STM32CubeMX之GPIO中断

参考文章《【STM32】HAL库 STM32CubeMX教程三----外部中断(HAL库GPIO讲解》 1 STM32CubeMX参数配置及其说明 配置好之后&#xff0c;生成代码 2 工程中的代码 用户在此函数中实现中断代码即可 /*** brief EXTI line detection callbacks.* param GPIO_Pin: Specifies the …

【计算机毕业设计】SSM停车场管理系统

项目介绍 本项目为后台管理系统&#xff0c;分为管理员、用户、工作人员三种角色&#xff1b; 管理员角色包含以下功能&#xff1a; 登陆页面,收入查看,停车卡开卡等功能。 用户角色包含以下功能&#xff1a; 用户登录,停车卡管理,优惠券管理,发送站内信,查看停车记录等功能…

wordpress个人博客/杂志主题Pin Premium

Pin Premium WordPress主题是针对博主的时尚且自适应的Pinterest风格主题。使用HTML5和CSS3技术创建&#xff0c;带有有效代码(两个演示)&#xff0c;完全响应&#xff0c;在所有移动设备上看起来完美&#xff0c;可在任何设备和 PC 上轻松使用。 响应式设计针对平板电脑和智能…

基于 Python+Django 技术栈,我开发了一款视频管理系统

学习过程中&#xff0c;遇到问题可以咨询作者 大家好&#xff0c;作为一名开发人员&#xff0c;平时比较愿意动手尝试各种有意思工具&#xff0c;因为笔者非常喜欢观看视频&#xff0c;尤其是YouTube、bilibili都是笔者非常喜欢的视频网站&#xff0c;所以想自己实现一个视频点…

astadmin安装querylist插件Puppeteer

我本来是想在linux服务器上安装&#xff0c;折腾了一天也没安装成功&#xff0c;由于急着用&#xff0c;就先做window10上安装了&#xff0c;以后有时间再研究centos7上安装 一 首先需要安装fastadmin 框架和querylist插件 这个大家可以自行安装&#xff0c;querylist安装地址…