当前位置: 首页 > news >正文

CPP从入门到入土之类和对象Ⅱ

一、六大默认成员函数

默认成员函数是用户没有显式实现,编译器自动生成的成员函数。
一个类,我们在不写的情况下,编译器会默认生成六个默认成员函数
在这里插入图片描述
本文详细介绍构造函数和析构函数

二、构造函数

构造函数虽名为构造函数,但是这个函数并不开辟空间创建对象(经常使用的局部对象是栈帧创建的)
构造函数的功能是:在对象实例化时初始化对象,类似于我们以前写的Init()函数
CPP引入构造函数,我们也就可以代替Init()函数了

构造函数的特点:

  • 函数值与类名相同
class Info{
public:
// 构造函数
	Info(){
	//...
	}
private:
//...
};
  • 无返回值(啥都不需要给,void也不用)
  • 对象实例化时(创建对象)系统会自动调用对应的构造函数
  • 支持重载,可以根据参数不同定义多个构造函数
  • 如果没有显式定义构造函数,CPP的编译器会自动生成一个无参的默认构造函数,一旦显式定义就不会生成

构造函数的类型

  1. 默认构造函数
    默认构造函数分为无参构造函数编译器自动生成的构造函数全缺省构造函数
    这三个函数有且只能存在一个:
    在这里插入图片描述

无参构造函数和 全缺省构造函数虽能构成函数重载,但是会产生调用歧义
总结一下: 默认构造函数是不用传实参的构造函数

class Info {
public:
	// 无参的默认构造函数
	Info() {
		_name = "UnKnow";
		_age = 0;
	}

	void Print() {
		cout << " 默认构造函数被调用" << endl;
		cout << _name << "  " << _age << endl;
	}
private:
	string _name;
	int _age;
};

int main() {
	Info I1;
	I1.Print();
}

在这里插入图片描述

  1. 带参数的构造函数
class Info {
public:
	// 带参的构造函数
	Info(string name, int age) {
		_name = name;
		_age = age;
	}

	void Print() {
		cout << " 默认构造函数被调用" << endl;
		cout << _name << "  " << _age << endl;
	}
private:
	string _name;
	int _age;
};

int main() {
	// 调用带参数的构造函数
	Info I2("kunkun", 18);
	I2.Print();
}

在这里插入图片描述

编译器自动生成的默认构造函数深度剖析

我们如果没有显式定义构造函数,编译器自动生成的构造函数会将对象初始化成什么呢?
类型的分类:
在这里插入图片描述

  • 内置类型:没有规定要处理(可处理可不处理,看编译器类型)
    在这里插入图片描述

  • 自定义类型:调用自定义类型对象的默认构造函数,本质是不断套娃,深挖!!!

在这里插入图片描述
分析一下:

D1这个对象中有三个内置类型成员变量和一个自定义类型成员变量,不写构造函数,首先自动生成Date()的默认构造函数,到private中发现三个内置类型,则不做处理,有个自定义类型_t,则去调用Time()的构造函数,发现有构造函数,则按照构造函数初始化命令初始化,如果Time()没有构造函数呢?那么_hour _minute _second也是内置类型,不做处理

在这里插入图片描述
注意:没有默认构造函数会报错
在这里插入图片描述

三、析构函数

析构函数构造函数功能相反,析构函数不是销毁对象,比如局部对象存在栈中,函数栈帧结束就自动销毁释放内存。
析构函数的功能是在对象销毁时完成对象中资源的清理释放
析构函数的功能类似于Destroy(),析构函数就可以完美替代Destroy()

析构函数的特点

  • 无参数无返回值,与构造函数类似
  • 函数名与类名相同,在类名前加字符 “~” eg:Name()
  • 一个类只能有一个析构函数,所以析构函数不能重载如果没有显式定义,系统会自动生成默认的析构函数
  • 对象生命周期结束,会自动调用析构函数
  • 与构造函数相同,编译器自动生成的析构函数对内置类型不做处理,对自定义类型则会调用它的析构函数
    注意:我们显式写析构函数,自定义类型成员会调用它的析构函数,换句话说,自定义类型成员无论什么情况下都会调用析构函数

析构函数的语法

class Test {
public:
	Test() {
		cout << "构造函数调用成功" << endl;
	}
	~Test() {
		cout << "析构函数调用成功" << endl;
	}
private:
};

int main() {
	cout << "程序开始运行" << endl;
	{
		Test T;// 构造函数被调用
	}// T生命周期结束
	cout << "程序运行结束";
}

在这里插入图片描述
总结:

  • 有资源需要手动清理,需要写析构函数
  • 有两种场景不需要写析构函数,利用默认生成的即可:
    1. 没有资源需要清理,例如:Date()日期列表全是局部成员
    2. 内置类型没有资源需要清理,剩下的全是自定义类型成员,且这些类有正确的析构函数 eg:
public:
    Engine() { std::cout << "Engine created.\n"; }
    ~Engine() { std::cout << "Engine destroyed.\n"; }
};

class Car {
public:
    Engine engine;
    int speed;
}; // Car的析构函数不需要手写

http://www.dtcms.com/a/80130.html

相关文章:

  • java TCP UDP 客户端访问例子和对比差异
  • Docker学习笔记(十)搭建Docker私有仓库
  • 第三章:单调栈
  • MATLAB神经网络优化1000个案例算法汇总
  • KV Cache 在自回归生成中的作用及显存优化
  • Python连接数据库进行增删改查
  • Postman高级功能深度解析:Mock Server与自动化监控——构建高效API测试与监控体系
  • DeepSeek+知网研学赋能研究生学习课程:降低科研压力与提升科研效率
  • 在Orin上查看CUDA cuDNN TensorRT的版本
  • Nat Commun | 单细胞和空间转录组学分析构建NSCLC免疫和非免疫区图谱
  • 示波器直流耦合和交流耦合的区别
  • MySQL为什么默认使用RR隔离级别?
  • 24. 状态模式
  • 栈/堆/static/虚表
  • Pytest基础使用
  • 【产品小白】如何运营一个成熟的产品
  • 《深度剖析:BERT与GPT——自然语言处理架构的璀璨双星》
  • SeaTunnel简易封装方案:让数据集成更简单
  • 「低延迟+快速集成:Amazon IVS如何重塑实时互动视频体验?」
  • python中的min函数的key的用法 - abs绝对值
  • 误杀!微软道歉了!
  • 【CVPR2024-工业异常检测】PromptAD方法(CLIP和提示学习)
  • HTML5响应式使用css媒体查询
  • 基于灵动微单片机SPIN系列的两轮车解决方案
  • 【记录】使用 Docker 搭建 MongoDB 分布
  • windows 平台编译openssl
  • Web开发-JS应用原生代码前端数据加密CryptoJS库jsencrypt库代码混淆
  • unityAB包(1/2)
  • Arduino示例代码讲解:Multiple tone player 多音播放器
  • 【优选算法】二分算法模板总结及应用