首页 > 编程语言 >【C++】类和对象(三)构造与析构

【C++】类和对象(三)构造与析构

时间:2024-06-20 14:59:51浏览次数:17  
标签:int 与析构 构造 编译器 默认 C++ year Date 构造函数

文章目录

一、类的6个默认成员函数

如果一个类中什么成员都没有,简称为空类。空类中并不是真的什么都没有。任何类在什么都不写时,编译器会自动生成以下6个默认成员函数。
默认成员函数:用户没有显式实现,编译器会生成的成员函数称为默认成员函数。

在这里插入图片描述

二、 构造函数

干嘛的?

构造函数是特殊的成员函数 用来初始化对象

语法定义

1️⃣函数名和类名相同
2️⃣没有返回值(不需要写)
代码演示:

class Date
{
public:
	//函数名与类名相同 没有返回值 不用写void 
	Date()
	{
		_year = 1;
		_month = 1;
		_day = 1;
	}

	void Print()
	{
		cout << _year << "-" << _month << "-" << _day << endl;
	}

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

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

3️⃣对象实例化时 编译器自动调用该函数,如果没有构造函数可调,会报错。
反汇编演示自动调用:
在这里插入图片描述
4️⃣构造函数可以重载(重载:函数名相同,参数不同)

class Date
{
public:
	Date()
	{
		_year = 1;
		_month = 1;
		_day = 1;
	}
	//构造函数可以重载
	Date(int year, int month , int day )
	{
		_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();
	Date d2(2024, 1, 27);
	d2.Print();
	return 0;
}

在这里插入图片描述

注意:无参的构造函数 和 全缺省的构造函数 可以同时存在类的定义里,但一般不这样写,因为调用会存在 歧义。

class Date
{
public:
	//无参的构造函数
	Date()
	{
		_year = 1;
		_month = 1;
		_day = 1;
	}
	//全缺省的构造函数
	Date(int year = 1, int month = 1, int day = 1)
	{
		_year = year;
		_month = month;
		_day = day;
	}
private:
	int _year;
	int _month;
	int _day;
};

int main()
{
	Date d1;
	Date d2(2024, 1, 27);
	return 0;
}

比如会出现如下报错:
在这里插入图片描述
构造函数可以带参数、也可以不带参数
带参数的情况:实例化对象时,直接把参数跟在对象后面就可以。
无参数的情况:实例化对象时,不能跟空括号()在对象后面,原因是:改写法无法跟函数声明区分开。

实践中,更多的情况直接用全缺省的构造函数

特性

思考下面的日期类我们没提供构造函数的情况是否会被初始化?

class Date
{
public:
	void Print()
	{
		cout << _year << "-" << _month << "-" << _day << endl;
	}

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

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

在这里插入图片描述

1、构造函数 ,是默认成员函数,程序员不写,编译器会生成一个,但是自动生成的构造函数初始化出的成员变量没有默认值(具体根据成员变量的类型而定)。

tips:C++ 中 数据类型分为

内置类型(基本类型): int /char /doube/指针… 语言自身定义的类型
自定义类型: struct /class

C++98 规定 ,编译器自动生成的 构造函数 对于内置类型不做处理,自定义类型会去调用他的默认构造函数。
演示代码:

class A
{
public:
	A()
	{
		cout << "A()" << endl;
		_a = 0;
	}
private:
	int _a;
};

class Date
{
public:
	void Print()
	{
		cout << _year << "-" << _month << "-" << _day << endl;
	}

private:
	// 内置类型 不做处理
	int _year ;
	int _month ;
	int _day;
	// 自定义类型 调默认构造
	A _aa;
};
int main()
{
	Date d1;
	d1.Print();
}

在这里插入图片描述

C++11 委员会对这个语法进行打补丁,对于内置类型 在成员变量声明位置 可以给缺省值 ,编译器自动生成的构造函数就会用程序员给出的这个缺省值初始化成员变量。

class A
{
public:
	A()
	{
		cout << "A()" << endl;
		_a = 0;
	}
private:
	int _a;
};

class Date
{
public:
	void Print()
	{
		cout << _year << "-" << _month << "-" << _day << endl;
	}

private:
	// C++11 内置类型 声明位置可以给缺省值
	int _year =1;
	int _month =1;
	int _day;
	// 自定义类型 调默认构造
	A _aa;
};
int main()
{
	Date d1;
	d1.Print();
}

在这里插入图片描述

综上总结

编译器自动生成的构造函数 在进行对象实例化时 对成员变量的初始化操作:

若成员变量是内置类型:编译器不做处理,程序员可以在成员变量声明位置 可以给缺省值 ,编译器自动生成的构造函数就会用程序员给出的这个缺省值初始化成员变量。

若成员变量是自定义类型:编译器自动生成的构造函数就会调用他的默认构造函数

程序员需要自己分析类型成员和初始化需求,绝大多数场景都需要程序员自己实现构造函数!

什么是默认构造函数?

编译器自动生成的构造函数只是 默认构造函数之一。无参数的构造函数全缺省的构造函数 也属于默认构造函数

总结:不需要传参 就可以调用的构造函数 ➡️默认构造函数,默认构造函数只能有一个

❓问题遗留:

class Time
{
public:
	// 没有默认构造函数
	Time(int hour)
	{
		cout << "Time()" << endl;
		_hour = 0;
		_minute = 0;
		_second = 0;
	}
private:
	int _hour;
	int _minute;
	int _second;
};

class Date
{
private:
	// 基本类型(内置类型)
	int _year;
	int _month;
	int _day;

	// 自定义类型
	Time _t;
}

int main()
{
	Date d;

	return 0;
}

代码问题描述:
当前time类中 我们显示定义了构造函数 ,则编译器不会自动生成默认构造函数。Data类包含time类,time类没有默认构造函数,导致Data类编译器也无法为这个类自动生成默认构造函数。

报错如下:在这里插入图片描述
此时,我们只能显示实现构造函数,详见 下期知识点初始化列表

三、析构函数

干嘛的 ?

清理资源,类似于 Desdory .

语法定义

1、析构函数名实在类名前面加上~

2、无参数无返回值类型

3、一个类只能有一个析构函数。程序员没定义,编译器自动生成析构函数。析构函数不能重载。

4、对象声明周期结束的时候,编译器自动调用

因为在函数栈帧里,所以先定义的后析构后定义的先析构

代码示例:我们创建不同生命周期不同作用域的对象,注意观察他们的析构顺序

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

	~Date()
	{
		cout << "~Date()->"<<_year<< endl;
	}

private:
	// 基本类型(内置类型)
	int _year;
	int _month;
	int _day;
};
void func()
{
	Date d3(3);
	static Date d4(4);
}

Date d5(5);
static Date d7(7);
Date d6(6);
static Date d8(8);

// 局部对象(后定义先析构) -》 局部的静态 -》全局对象(后定义先析构)
int main()
{
	Date d1(1);
	Date d2(2);
	func();

	return 0;
}

析构顺序

局部对象(后定义先析构) ➡️ 局部的静态 ​ ➡️ 全局对象(无论静态or非静态 都是后定义先析构)

在这里插入图片描述

默认生成的析构函数跟构造函数类似,

如果要清理的资源是内置类型,则不做处理。若是自定义类型的成员,则编译器去调用它的析构函数

其他的默认成员函数我们会在下节介绍~

标签:int,与析构,构造,编译器,默认,C++,year,Date,构造函数
From: https://blog.csdn.net/weixin_61400132/article/details/139781840

相关文章

  • 0基础学C++ | 第02天 | 基础知识 | sizeof关键字 | 浮点型 | 字符型 | 转义字符 | 字
    前言  该文章是在B站学习C++,同时结合自己的理解整理的笔记,视频连接:https://www.bilibili.com/video/BV1et411b73Z/?p=8&spm_id_from=333.880.my_history.page.click 1、sizeof关键字作用:利用sizeof关键字可以统计数据类型所占用的内存大小语法:sizeof(数据类型/变量)#incl......
  • c++提供的类型转换
    在C++中,提供了几种不同的类型转换方式,每种转换方式有其特定的使用场景和语义。以下是C++中常见的几种类型转换方式:静态转换(StaticCast):使用static_cast进行转换,用于基本类型之间的转换,如数值类型的转换、非const对象指针的转换等。静态转换在编译时进行,不提供运行时的检......
  • 【C++修行之道】C/C++内存管理
    目录一、C/C++内存分布 1.选择题: 2.填空题: 3.sizeof和strlen区别? 二、C语言中动态内存管理方式:malloc/calloc/realloc/free 1.malloc/calloc/realloc的区别是什么?2.这里需要free(p2)吗?三、C++内存管理方式3.1new/delete操作内置类型3.2new和delete操作......
  • 在 Visual Studio 2022 (Visual C++ 17) 中使用 Visual Leak Detector
    1问题描述1.1内存泄漏的困扰和解决之道在C/C++程序开发过程中,开发者受益于C/C++的强大,与此同时也承受着C/C++程序开发的额外风险。像Java、C#这类带GC(内存垃圾回收)的编程语言,在内存管理方面,给开发者提供了“保姆级”的封装,开发者不用太关注内存泄漏问题[1]。但是C/C++的哲学......
  • 从0开始C++(三):构造函数与析构函数详解
    目录构造函数 构造函数的基本使用构造函数也支持函数重载构造函数也支持函数参数默认值构造初始化列表拷贝构造函数浅拷贝和深拷贝析构函数 总结练习一下ヽ( ̄▽ ̄)ノ 构造函数 构造函数的基本使用构造函数是一种特殊的成员函数,用于创建对象时初始化,写法上有以下......
  • C/C++ 内存安全注意事项
    C/C++内存安全相关的注意事项主要如下:避免数组越界访问:数组越界是一种常见的安全漏洞,可能导致程序崩溃或被黑客利用。在访问数组元素时,应确保下标值不超过数组的边界。可以使用边界检查或安全的访问函数来预防此类问题。防止内存泄漏:C/C++中,内存管理需要程序员手动进行。......
  • 【C++】vector的使用和模拟实现
    ❤️欢迎来到我的博客❤️前言vector示可变大小数组的序列容器就像数组一样,vector也采用的连续存储空间来存储元素既然都是数组并且都可以动态增长那么vector能不能替代string呢?答案是不能原因如下:string和vector在结构上有所不同不同点:string要求末尾有’\0’(自动......
  • C++ Windows Hook使用
    GitHub-microsoft/Detours:DetoursisasoftwarepackageformonitoringandinstrumentingAPIcallsonWindows.Itisdistributedinsourcecodeform./*挂载钩子setdll/d:C:\Users\g\source\repos\LotTest\Release\lotDll.dllC:\Users\g\source\repo......
  • 基于QT和C++实现的中国象棋
    一,源码board.h#ifndefBOARD_H#defineBOARD_H#include<QWidget>#include"Stone.h"classBoard:publicQWidget{Q_OBJECTpublic:explicitBoard(QWidget*parent=0);bool_bRedTurn;//红方先走int_currentPlayer;//当前玩......
  • C++学习(22)
    #学习自用#计时计时可以计算出执行代码时花费了多长时间,对于同样的目的,我们可以通过不同的代码实现,而执行时间长短是评价一串代码性能如何的指标。#include<iostream>#include<string>#include<chrono>#include<thread>usingnamespacestd;intmain(){ autostar......