C++入门之类和对象(中)

C++入门之类和对象(中)

文章目录

  • C++入门之类和对象(中)
    • 1. 类的6个默认对象
    • 2. 构造函数
      • 2.1 概念
      • 2.2 特性
      • 2.3 补丁
    • 3. 析构函数
      • 3.1 概念
      • 3.2 特性
      • 3.3 总结
    • 4. 拷贝构造函数
      • 4.1 概念
      • 4.2 特性
      • 4.3 总结

1. 类的6个默认对象

如果一个类中什么都没有,那么这个类就是一个空类。但是,任何类如果什么都不写的话,编译器会自动生成6个默认成员函数

默认成员函数:用户没有显式实现(用户没有写),编译器自动生成的成员函数被称为默认成员函数

class Data{};

在这里插入图片描述

2. 构造函数

2.1 概念

假设有以下类:

#include <iostream>
using namespace std;
class Date
{
public:
	void Init(int year = 2024, int month = 4, int day = 15)
	{
		_year = year;
		_month = month;
		_day = day;
	}
	void Print()
	{
		cout << _year << "-" << _month << "-" << _day << endl;
	}
private:
	int _year;
	int _month;
	int _day;
};


int main()
{
	Date d1;
	d1.Init();
	d1.Print();

	Date d2;
	d2.Init(2024, 5, 1);
	d2.Print();

	return 0;
}

上述类中是使用Init函数对类进行初始化,Init使用全缺省参数,如果没有传值的话,使用缺省值初始化,但是对于这这种类,就算不初始化也不会有什么问题,但是对于顺序表,链表等,如果不初始化就会报错,往往我们会容易忘记调用初始化,这时候,构造函数就派上用场了

构造函数是一种特殊的函数,名字与类名相同,没有返回值(在默认成员函数中,没有返回值指的都是不写),在创建类对象时由编译器自动调用,保证每个成员都有一个初始值,并且在类对象整个生命周期只会调用一次

2.2 特性

构造函数是一种特殊的函数,构造函数并不是用于开辟空间创建对象,而是为对象进行初始化

特征

  1. 函数名与类名相同
  2. 函数没有返回值(不写返回值)
  3. 对象实例化时编译器会自动调用
  4. 构造函数可以重载(可以根据需求写多个初始化方式)
  5. 如果类中没有显式定义构造函数(没有写),编译器就会自动生成一个无参的构造函数,反之,编译器则不会生成
  6. 由编译器生成的无参构造函数,不会对类中的内置类型(int char等等)进行处理,但是对调用类中自定类型(class struct union等等)的构造函数,如果类中自定类型还是没有则也不处理
    C++中没有规定对自定类型(class struct union等等)初始化成0或者其他,取决于编译器的实现
  7. 无参构造函数全缺省的构造函数由编译器自动生成构造函数都可以被称为默认参构造函数,但是默认参构造函数只能存在一个

示例1:

#include <iostream>
using namespace std;
class Date
{
public:
	//Date(int year, int month, int day) (这种写法会报错,这种不是默认的构造函数)
	Date(int year = 2024, int month = 4, int day = 15)
	{
		_year = year;
		_month = month;
		_day = day;
	}
	void Print()
	{
		cout << _year << "-" << _month << "-" << _day << endl;
	}
private:
	int _year;
	int _month;
	int _day;
};


int main()
{
	Date d1;//调用全缺省的构造函数(2024-4-15)
	d1.Print();

	return 0;
}

示例2:

#include <iostream>
using namespace std;
class Time
{
private:
	int _hour;
	int _minute;
	int _second;
};
class Date
{
public:
	
	void Print()
	{
		cout << _year << "-" << _month << "-" << _day << endl;
	}
private:
	int _year;
	int _month;
	int _day;
	Time a;
};


int main()
{
	Date d1;
	d1.Print();

	return 0;
}

在这里插入图片描述

示例3:

#include <iostream>
using namespace std;
class Date
{
public:
	Date()
	{
	}
	Date(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()
{
	Date d1;
	d1.Print();

	return 0;
}

存在多个构造函数,报错

2.3 补丁

由于不对内置类型进行初始化,所以在C++ 11中,打了一个补丁,允许内置成员在声明时可以给一个默认值

#include <iostream>
using namespace std;
class Date
{
public:
	void Print()
	{
		cout << _year << "-" << _month << "-" << _day << endl;
	}
private:
	int _year = 2024;
	int _month = 4;
	int _day = 15;
};


int main()
{
	Date d1;
	d1.Print();

	return 0;
}

用声明时的默认值初始化(2024-4-15)

总结:
一般情况下,构造函数都要由我们自己实现,少部分情况下可以不用实现(如果类中只有自定类型,而这个自定类型内部存在构造函数),例如:MyQueue

3. 析构函数

3.1 概念

析构函数是与构造函数相反的一种特殊函数,析构函数不是对对象进行销毁,局部变量的销毁是由编译器处理的,而是析构函数是对对象中资源的清理,且会在对象销毁时自动调用

3.2 特性

  1. 在类名前面加上~
  2. 无参数无返回值(不写返回值)
  3. 一个类只有一个析构函数,如果没有显式定义(没有写),则编译器会自动生成默认析构函数(由于没有参数,析构函数不能重载)
  4. 在对象生命周期结束时,编译器会自动调用析构函数
  5. 与构造函数相似的是,析构函数不会对内置类型进行处理,对自定类型则是调用其析构函数

示例:

#include <iostream>
using namespace std;
class Stack
{
public:
	Stack(int n = 4)
	{
		cout << "Stack()" << endl;
		int* tmp = (int*)malloc(sizeof(int) * n);
		if (nullptr == tmp)
		{
			perror("malloc fail");
			return;
		}

		_arr = tmp;
		_capacity = n;
		_size = 0;
	}
	void Push(int x)
	{
		//扩容
		_arr[_size] = x;
		_size++;
	}
	~Stack()
	{
		cout << "~Stack()" << endl; //方便查看
		if (_arr) //防止被多次销毁,加个判断
		{
			free(_arr);
			_arr = nullptr;
			_capacity = 0;
			_size = 0;
		}
	}
private:
	int* _arr;
	int _size;
	int _capacity;
};
int main()
{
	Stack s;
	s.Push(1);
	s.Push(2);
	s.Push(3);
	s.~Stack();
	return 0;
}

在这里插入图片描述

析构函数也是可以显式调用的

3.3 总结

  1. 在没有需要资源清理的时候可以不写析构函数,
    a. 如Date类,没有需要清理的内置类型
    b.没有需要清理的内置类型,剩下的其他自定类型中存在析构函数,如MyQueue,也不需要写析构函数
    2.有资源清理就要写析构函数,如Stack,List

4. 拷贝构造函数

4.1 概念

拷贝构造函数:只有一个形参,该形参为本类型对象的引用(一般会使用const修饰),在用已经存在的类类型对象时创建新对象时会由编译器自动调用

4.2 特性

  1. 是构造函数的一种重载形式(函数名与类型一致)
  2. 拷贝构造函数的参数只能有一个,且得是类类型对象的引用,否则在使用拷贝构造函数会直接报错(引发无穷递归调用)
  3. 如果没有显式定义,编译器会自动生成默认的拷贝构造函数,默认的拷贝构造函数会对内置类型进行处理,按内存存储按字节序完成拷贝,也被称为浅拷贝或者值拷贝

示例1:

#include <iostream>
using namespace std;
class Date
{
public:
	Date(int year = 1, int month = 1, int day = 1)
	{
		_year = year;
		_month = month;
		_day = day;
	}

	void Init(int year = 2024, int month = 4, int day = 15)
	{
		_year = year;
		_month = month;
		_day = day;
	}
	void Print()
	{
		cout << _year << "-" << _month << "-" << _day << endl;
	}
private:
	int _year;
	int _month;
	int _day;
};


int main()
{
	Date d1(2024,4,15);

	Date d2 = d1; //与下面创建对象d3是等价的,两种写法
	d2.Print();

	Date d3(d1);
	d3.Print();

	return 0;
}

示例2:

#include <iostream>
using namespace std;
class Stack
{
public:
	Stack(int n = 4)
	{
		cout << "Stack()" << endl;
		int* tmp = (int*)malloc(sizeof(int) * n);
		if (nullptr == tmp)
		{
			perror("malloc fail");
			return;
		}

		_arr = tmp;
		_capacity = n;
		_size = 0;
	}
	void Push(int x)
	{
		//扩容
		_arr[_size] = x;
		_size++;
	}
	~Stack()
	{
		cout << "~Stack()" << endl;
		if (_arr)
		{
			free(_arr);
			_arr = nullptr;
			_capacity = 0;
			_size = 0;
		}
	}
private:
	int* _arr;
	int _size;
	int _capacity;
};
int main()
{
	Stack s1;
	s1.Push(1);
	s1.Push(2);
	s1.Push(3);

	Stack s2 = s1;

	return 0;
}

代码运行结果:
报错

  编译器生成的默认拷贝构造是不够用,在上述代码中,s2对象使用s1对象的拷贝,由于是浅拷贝,会将s1中的内容原封不动的拷贝给s2,因此s1和s2调用的是同一块空间,在调用析构函数时,s1将空间释放了,但是s2中存放的还是s1的空间,因为还会再释放一次,一块内存空间的多次释放,会造成程序奔溃。同时在对任意一个栈中push数据的时候,另一个栈中的size是不会加的,但是共用的是同一块空间,数据丢失等等问题

示例3:错误写法

#include <iostream>
using namespace std;
class Date
{
public:
	Date(int year = 1, int month = 1, int day = 1)
	{
		_year = year;
		_month = month;
		_day = day;
	}

	Date(Date d) //错误写法 会引发无穷递归
	{
		_year = d._year;
		_month = d._month;
		_day = d._day;
	}
private:
	int _year;
	int _month;
	int _day;
};

Date Func(Date d)
{
	Date tmp(d);
	return tmp;
}

int main()
{
	Date d1(2024, 4, 15);
	Func(d1);

	return 0;
}

在返回一个局部变量时,由于局部变量出作用域就销毁了,所以会将局部变量拷贝给一个临时变量,在给拷贝给临时变量时,又会调用拷贝构造函数,在调用拷贝构造函数时,又会将返回值拷贝给一个临时变量,造成无穷递归

4.3 总结

  1. 在类中,如果没有涉及需要资源管理的内置类型,是可以不写拷贝构造函数的,编译器自动生成的浅拷贝就够用,但是一旦涉及,就需要自己实现拷贝构造函数了
  2. 拷贝构造函数的参数只有一个且必须是类类型对象的引用,使用传值方式编译器直接报错,因为会引发无穷递归调用

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

NLP任务全览:涵盖各类NLP自然语言处理任务及其面临的挑战

自然语言处理(Natural Language Processing, 简称NLP&#xff09;是计算机科学与语言学中关注于计算机与人类语言间转换的领域。NLP将非结构化文本数据转换为有意义的见解&#xff0c;促进人与机器之间的无缝通信&#xff0c;使计算机能够理解、解释和生成人类语言。人类等主要…

chatgpt免费使用网站

在人工智能的浪潮中&#xff0c;OpenAI的ChatGPT作为一款前沿的语言处理工具&#xff0c;已经引起了广泛的关注和讨论。 ChatGPT以其卓越的语言理解和生成能力&#xff0c;为用户提供了多样化的应用场景&#xff0c;从日常对话、编程辅助到内容创作等。然而&#xff0c;对于许…

FL Studio21.2.4重磅发布更新发布功能介绍2024最新

FL Studio21是一款功能强大的数字音频工作站&#xff08;DAW&#xff09;&#xff0c;它在音乐制作领域占据着重要的地位。以下是对FL Studio 21的详细介绍&#xff1a; 一、功能与特点 音频编辑&#xff1a;FL Studio 21提供了强大的音频编辑功能&#xff0c;包括波形编辑&a…

车载诊断系统应用方案选型,ESP8266方案让成本降低了35%,销售数据提升47%

车载诊断系统简称OBD&#xff0c;这个系统随时监控发动机的运行状况和尾气后处理系统的工作状态&#xff0c;一旦发现有可能引起排放超标的情况&#xff0c;会马上发出警示。当系统出现故障时&#xff0c;故障灯(MIL)或检查发动机(Check Engine)警告灯亮&#xff0c;同时OBD系统…

分支结构(if)

一.关于if 1.什么是if 在我们判断一个条件的时候&#xff0c;需要执行一些条件&#xff0c;这时就需要我们的"if"闪亮登场。 2.怎么使用if if是这样使用的&#xff1a; if(判断条件){判断过后执行的 } 然后我们需要一道例题洛谷的P5712 【深基3.例4】Apples&am…

SVN泄露(ctfhub)

目录 下载安装dvcs-ripper 使用SVN 一、什么是SVN&#xff1f; 使用SVN能做什么&#xff1f; 二、SVN泄露&#xff08;ctfhub&#xff09; SVN源代码漏洞的主要原因&#xff1a; 工具准备&#xff1a;dirsearch、dvcs-ripper 网络安全之渗透测试全套工具篇&#xff08;内…

正式发布的Spring AI,能让Java喝上AI赛道的汤吗

作者:鱼仔 博客首页: https://codeease.top 公众号:Java鱼仔 前言 最近几年AI发展实在太快了&#xff0c;仿佛只要半年没关注&#xff0c;一个新的大模型所产生的效果就能超越你的想象。Java在AI这条路上一直没什么好的发展&#xff0c;不过Spring最近出来了一个新的模块叫做S…

【学习笔记】Vue3源码解析:第五部分 - 实现渲染(2)

课程地址&#xff1a;【已完结】全网最详细Vue3源码解析&#xff01;&#xff08;一行行带你手写Vue3源码&#xff09; 第五部分-&#xff1a;&#xff08;对应课程的第33 - 35节&#xff09; 第33节&#xff1a;《讲解组件渲染流程》 1、在 render 函数中拿到虚拟dom vnode后…

Ubuntu的终端中启用鼠标左键即为选中复制,右键粘贴的功能

在Ubuntu终端中启用鼠标复制和粘贴的功能需要进行一些设置。 首先&#xff0c;打开终端窗口&#xff0c;在菜单栏中找到“Edit”选项&#xff0c;点击“Profile Preferences”。然后&#xff0c;在“General”选项卡中&#xff0c;勾选“Use custom font”选项&#xff0c;可以…

博客文章:AWS re:Invent 2023 新产品深度解析 - 第四部分

TOC &#x1f308;你好呀&#xff01;我是 是Yu欸 &#x1f30c; 2024每日百字篆刻时光&#xff0c;感谢你的陪伴与支持 ~ &#x1f680; 欢迎一起踏上探险之旅&#xff0c;挖掘无限可能&#xff0c;共同成长&#xff01; 写在最前面 去年发布文章的一部分&#xff0c;由于内…

微光成束,星火燎原,酷雷曼扶持政策再升级!

从北纬 18 度的三亚海角&#xff0c; 到北纬 53 度的漠河不夜城&#xff0c; 从东经 81 度的塞外江南伊犁&#xff0c; 到东经 120 度的上海魔都。 酷雷曼合作商为客户服务的范围 遍及全国 300 余个地区&#xff0c; 跨越了东南西北的辽阔地域。 即便如此&#xff0c; 面…

基于Bootstrap 5的创新网络服务公司网站模板

一.前言 这个网站的内容包括&#xff1a; 标题&#xff1a;Web service - Business Category Bootstrap Responsive Website Template - Home导航栏&#xff1a;Home, About, Services, Pages&#xff08;包括Blog posts、Blog single、404、Landing page等页面&#xff09;、…

fastjson转换json时默认将属性第一个字母转小写

描述&#xff1a; 我新建了一个实体类&#xff0c;但是实体类的首字母是大写的&#xff0c;但是使用fastjson后打印的&#xff0c;Json字符串首字母却是小写的&#xff0c;这是fastjson的一个bug 实体类&#xff1a; Json字符串&#xff1a; 解决方法&#xff1a; 一、使…

一个 .net 8 + Azure 登录 + Ant Design Blazor 的基本后台框架

一个 .net 8 Azure 登录 Ant Design Blazor 的基本后台框架 主界面使用了 Ant Design Blazor 项目模板搭建 后台技术是 .net 8 Blazor run at server 模式 登录方式使用 Azure 实现了菜单导航和路由 此外实现了读取和修改本地Json文件的功能&#xff0c;不是必须的&#x…

Github 2024-04-16Python开源项目日报 Top10

根据Github Trendings的统计,今日(2024-04-16统计)共有10个项目上榜。根据开发语言中项目的数量,汇总情况如下: 开发语言项目数量Python项目10TypeScript项目1Vue项目1系统设计指南 创建周期:2507 天开发语言:Python协议类型:OtherStar数量:241693 个Fork数量:42010 次…

MySql8快速迁移版的制作过程

首先说明&#xff0c;mysql 8的安装不同与mysql5.x。 做程序的朋友都知道&#xff0c;程序好做&#xff0c;客户难伺候&#xff0c;因为限于用户的情况&#xff0c;如何能让用户把程序运行起来很关键&#xff0c;比如日前我在做 山东高中信息技术 学考 考前练习 系统时&#x…

3d模型附加之后怎么分离?---模大狮模型网

在3D建模过程中&#xff0c;有时候我们需要将多个物体合并成一个模型&#xff0c;以便于进行操作或者导出。然而&#xff0c;在某些情况下&#xff0c;我们也需要将这些附加的物体进行分离&#xff0c;以便对它们进行单独的编辑或者处理。本文将介绍在3D建模软件中如何将附加的…

密文字段模糊检索方案

代码地址: https://github.com/zuiyu-main/EncryptDemo https://mp.weixin.qq.com/s/cXOg1tiMtJz2eibDZmXHUQ 在个别特殊领域中&#xff0c;数据的安全问题是非常的重要的&#xff0c;所以需要数据库存储的数据是需要加密存储的。所以也就引申出来本文这个问题&#xff0c;加密…

顺丰同城急送API对接(附源码)

一、背景 最近公司让我对接顺丰同城急送的API&#xff0c;讲讲里面需要注意的几点 官方的API文档有些示例代码也不全&#xff0c;具体细节不多说&#xff0c;如果你现在也需要对接他们API&#xff0c;可以参考本篇博客再配合官方文档结合起来看&#xff0c;可以让您再开发的时…

深度学习--CNN应用--VGG16网络和ResNet18网络

前言 我们在学习这两个网络时&#xff0c;应先了解CNN网络的相关知识 深度学习--CNN卷积神经网络&#xff08;附图&#xff09;-CSDN博客 这篇博客能够帮我们更好的理解VGG16和RetNet18 1.VGG16 1.1 VGG简介 VGG论文网址&#xff1a;VGG论文 大家有兴趣的可以去研读一下…