C++入门之类和对象

news2025/2/7 14:43:06

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. 拷贝构造函数的参数只有一个且必须是类类型对象的引用,使用传值方式编译器直接报错,因为会引发无穷递归调用

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

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

相关文章

UE5 C++ TimeLine 时间轴练习

一. Actor引入头文件 #include "Components/TimelineComponent.h" 声明CurveFloat 和 TimelineComponent UPROPERTY(EditAnywhere,BlueprintReadWrite,Category "MyCurve")UCurveFloat* MyCurveFloat;UPROPERTY(EditAnywhere, BlueprintReadWrite, Cate…

科技助力上亿用户隐私安全保护,合合信息两款产品再获CCIA PIA星级标识

随着互联网技术的飞速发展&#xff0c;个人信息的收集、存储、使用和传输变得日益频繁&#xff0c;其泄露和滥用的风险也随之增加&#xff0c;个人信息保护已成为社会共同关注的热点议题。近期&#xff0c;“中国网络安全产业联盟&#xff08;CCIA&#xff09;数据安全工作委员…

密码学 | 椭圆曲线数字签名方法 ECDSA(上)

目录 1 ECDSA 是什么&#xff1f; 2 理解基础知识 3 为什么使用 ECDSA&#xff1f; 4 基础数学和二进制 5 哈希 6 ECDSA 方程 7 点加法 8 点乘法 9 陷阱门函数&#xff01; ⚠️ 原文&#xff1a;Understanding How ECDSA Protects Your Data. ⚠️ 写在前面…

OpenHarmony轻量系统开发【9】WiFi之STA模式连接热点

9.1AT指令操作WiFi 我们可以使用AT指令进行Hi3861 WiFi操作&#xff0c;连接热点、ping服务器等。 但是很多时候&#xff0c;我们需要实现开机后自动连接到某个热点&#xff0c;光靠AT指令不行。 Hi3861 为我们提供了WiFi操作的相关API&#xff0c;方便我们编写代码&#xff0…

GitLab 安全漏洞 CVE-2022-1162 如何解决?

本文来自极狐GitLab 官方公众号【极狐GitLab】&#xff0c;原文链接&#xff1a;https://mp.weixin.qq.com/s/JVpA14HHWgt58s3vM5TRcA。 GitLab 是一个全球知名的一体化 DevOps 平台&#xff0c;很多人都通过私有化部署 GitLab 来进行源代码托管。极狐GitLab &#xff1a;https…

文字转语音工具:GPT-SoVITS

诸神缄默不语-个人CSDN博文目录 OpenAI官方的TTS模型我在这篇博文中给出了使用教程&#xff1a;ChatGPT 3.5 API的调用不全指南&#xff08;持续更新ing…&#xff09; - 知乎 但是OpenAI的TTS对中文支持不好&#xff0c;有一种老外说中文的美&#xff0c;所以本文介绍另一个…

2024软考中项考哪个版本?应该该如何备考?

2024年1月&#xff0c;备受瞩目的软考中级系统集成项目管理工程师官方教程终于迎来了久违的大改版。为确保广大考生能够有充足的准备时间&#xff0c;软考中项的考试时间被顺延至同年11月&#xff0c;届时&#xff0c;这也将成为软考中项首次依据第3版考纲进行的考试。 新教材核…

数图智慧零售解决方案,赋能零售行业空间资源价值最大化

数图智慧零售解决方案 赋能零售行业空间资源价值最大 在激烈的市场竞争中&#xff0c;如何更好地提升空间资源价值&#xff0c;提高销售额&#xff0c;成为行业关注的焦点。近日&#xff0c;NIQ发布的《2024年中国饮料行业趋势与展望》称&#xff0c;“在传统零售业态店内&…

CSS特效---跳动的文字

1、演示 2、一切尽在代码中 <!--* Author: your name* Date: 2023-10-03 14:42:44* LastEditTime: 2023-10-03 14:56:26* LastEditors: DESKTOP-536UVPC* Description: In User Settings Edit* FilePath: \css-special-effects\跳动的文字.html --> <!DOCTYPE html>…

ARM看门狗定时器

作用 在S3C2440A中&#xff0c;看门狗定时器的作用是当由于噪声和系统错误引起的故障干扰时恢复控制器的工作。 也就是说&#xff0c;系统内部的看门狗定时器需要在指定时间内向一个特殊的寄存器内写入一个数值&#xff0c;俗称喂狗。 如果喂狗的时间过了&#xff0c;那么看门…

行式存储VS列式存储对比

行式存储&#xff1a; 一行代表一个记录的所有字段。 可以快速读取和写入单条记录。 如果要检索一条数据&#xff0c;数据库会读取or写入整条记录&#xff0c;包含所有相关字段。 列式存储&#xff1a; 表中每一列的数据连续存放。这种方式在需要对某一列进行大量运算或分析时…

AI预测福彩3D第37弹【2024年4月16日预测--第8套算法开始计算第5次测试】

今天咱们继续测试第8套算法和模型&#xff0c;今天是第5次测试&#xff0c;目前的测试只是为了记录和验证&#xff0c;不建议大家盲目跟买。。我的目标仍旧是10次命中3-4次!~废话不多说了&#xff0c;直接上结果&#xff01; 2024年4月16日3D的七码预测结果如下 第一套…

数字乡村创新实践探索农业现代化路径:科技赋能农业产业升级、提升乡村治理效能与农民幸福感

随着信息技术的快速发展和数字化时代的到来&#xff0c;数字乡村建设正成为推动农业现代化、提升农业产业竞争力、优化乡村治理以及提高农民幸福感的重要途径。本文将围绕数字乡村创新实践&#xff0c;探讨其在农业现代化路径中的积极作用&#xff0c;以及如何通过科技赋能实现…

C语言中的数据结构- -链表(1)

前言 前几节我们学习了C语言中的数据结构--顺序表&#xff0c;该数据结构类型相较于普通的数组而言有很多的优势&#xff0c;但是它还是在一定层面上存在着一些缺陷&#xff0c;可以归纳为以下三点&#xff1a; 1. 中间/头部的插⼊删除&#xff0c;时间复杂度为O(N)【数组的遍…

每日一VUE——组件基础

文章目录 认识组件如何使用注册方式 组件间传递数据propsprops的验证 组件事件组件事件的验证v-model与自定义事件结合使用 组件插槽动态组件 认识组件 组件由template&#xff0c;script&#xff0c;style三部分组成。 如何使用 定义组件注册组件调用组件 注册方式 全局注…

在STM32中给固定的地址写入一个值,并通过memory窗口进行查看

首先对STM32中存储数据的地方有一个了解 一个是FLASH,一个是RAM RAM是易失存储器&#xff0c;FLASH是非易失存储器&#xff0c;这是最直观的解释。 主要记住以下几点&#xff1a; RAM&#xff08;随机存储器&#xff09;&#xff1a;既可以从中读取数据&#xff0c;也可以写…

面试八股——数据库——分库分表

垂直策略 垂直分库 垂直分表 水平策略 水平分库 水平分表&#xff08;和水平分库差不多&#xff0c;区别是但这些表可以在同一个库内&#xff09;

spring-cloud微服务gateway

核心部分&#xff1a;routes(路由)&#xff0c; predicates(断言)&#xff0c;filters(过滤器) id&#xff1a;可以理解为是这组配置的一个id值&#xff0c;请保证他的唯一的&#xff0c;可以设置为和服务名一致 uri&#xff1a;可以理解为是通过条件匹配之后需要路由到&…

Oauth2.1第三方授权前后端分离实现

前言 Spring Cloud 整合 Spring Security Oauth2 请看我上一篇文章 在当今的数字化时代&#xff0c;随着微服务架构的流行和前后端分离技术的广泛应用&#xff0c;如何实现安全、高效的用户认证与授权成为了开发者们面临的重要挑战。Spring Cloud与Spring Security OAuth2作为J…

小程序商城和微商城的区别

移动互联网电商发展迅速&#xff0c;各种商城系统的类型越来越多&#xff0c;人们选择要从多方面考量再进行评估&#xff0c;选择过程变得困难了很多&#xff0c;比如现在火热的微商城和小程序商城&#xff0c;很多人都不太能分清楚。今天&#xff0c;我们就一起来看看这两种商…