首页 > 编程语言 >【C++】踏上C++的学习之旅(七):深入“类和对象“世界,掌握编程的黄金法则(二)(内含构造函数和析构函数)

【C++】踏上C++的学习之旅(七):深入“类和对象“世界,掌握编程的黄金法则(二)(内含构造函数和析构函数)

时间:2024-11-11 19:15:27浏览次数:7  
标签:函数 int C++ 编译器 默认 Date 和析构 构造函数

文章目录


哈哈哈

前言

踏上C++的学习之旅(六):深入“类和对象“世界,掌握编程的黄金法则(一)中,我给大家讲解了"类"的定义以及如何使用类创建出对象。那么在本文中,我们将继续深入了解"类和对象"的细节,其中我们会给大家深入的讲解构造函数析构函数

话不多说,让我们继续探索"类和对象"世界吧!!!

哈哈哈

1. 类的6个默认的成员函数

如果一个类中什么成员都没有,我们简称它为"空类"。

//A类就是一个空类
class A{};

那空类中真的什么都没有没有吗?其实不然,任何类在什么都不写时,编译器会默认生成6个默认的成员函数。(这个点十分重要!后面再每个章节中,我会带着大家感受这些默认成员函数的存在)

那这里我们就可以给默认成员函数下一个定义了:

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

这里我先大家简单认识一下这6个默认成员函数,文章的后面还会再次讲解的!

6个默认成员函数
以上的6个默认成员函数,我们重点学习前4个(构造函数、析构函数、拷贝构造函数以及赋值运算符重载函数)。

本文会先重点讲解构造函数和析构函数!!!


2. 构造函数和析构函数的“好处”

为了让大家更好的理解构造函数和析构函数存在的价值,这里我会给大家举一个例子。(其中可能会涉及一些构造函数和析构函数的语法,如果大家不是很了解的话,可以想理解这两个函数带来的好处,后面我会重点讲解这两个函数)

如果我们按照C语言的那套思维,用C++实现一个栈的话,我们是这么写的:

typedef int DataType;
class Stack
{
public:
	void Init()
	{
		_array = (DataType*)malloc(sizeof(DataType) * 3);
		if (NULL == _array)
		{
			perror("malloc申请空间失败!!!");
			return;
		}
		_capacity = 3;
		_size = 0;
	}
	void Push(DataType data)
	{
		CheckCapacity();
		_array[_size] = data;
		_size++;
	}
	void Pop()
	{
		if (Empty())
			return;
		_size--;
	}
	DataType Top() { return _array[_size - 1]; }
	int Empty() { return 0 == _size; }
	int Size() { return _size; }
	void Destroy()
	{
		if (_array)
		{
			free(_array);
			_array = NULL;
			_capacity = 0;
			_size = 0;
		}
	}
private:
	void CheckCapacity()
	{
		if (_size == _capacity)
		{
			int newcapacity = _capacity * 2;
			DataType* temp = (DataType*)realloc(_array, newcapacity *
				sizeof(DataType));
			if (temp == NULL)
			{
				perror("realloc申请空间失败!!!");
				return;
			}
			_array = temp;
			_capacity = newcapacity;
		}
	}
private:
	DataType* _array;
	int _capacity;
	int _size;
};

int main()
{
	Stack s;
	s.Init(); //对创建栈变量s进行初始化
	s.Push(1);
	s.Push(2);
	s.Push(3);
	s.Push(4);

	printf("%d\n", s.Top());
	printf("%d\n", s.Size());
	s.Pop();
	s.Pop();
	printf("%d\n", s.Top());
	printf("%d\n", s.Size());
	s.Destroy(); //对创建栈变量s进行销毁,释放动态申请的内存
	return 0;
}

我们可以运行代码,看一下程序的结果:
运行结果

不过上面的代码对于我们来说不是那么的友好,为什么这么说呢?
我们每一次在main函数创建一个Stack的变量,都得初始化一次,完事后,还得销毁这个变量。 而且每当代码量增大时,我们往往会忘记这两个动作,导致程序出现意想不到的错误。那有的读者就会问了,我不初始化行不行?在C++的编译器上面跑的话,肯定是会报错的!
这里我用C++的编译器给大家做一个演示(不初始化Stack定义的变量):
结果
可以看到这里的退出码非0,这就意味着程序出问题了。

那我们该怎么解决我是不是会忘记给变量初始化和销毁的问题呢?
此时,构造函数和析构函数就闪亮登场了。我在上面给大家见过构造函数的作用时完成对成员变量的初始化工作,而析构函数时完成对对象的清理工作,而且这个时编译器自动调用的,不需要我们显式调用。这不就完美的解决我们的问题了。这个就是构造函数和析构函数能给我们的好处!

经过改造的代码:

typedef int DataType;
class Stack
{
public:
	Stack() //这个就是构造函数
	{
		_array = (DataType*)malloc(sizeof(DataType) * 3);
		if (NULL == _array)
		{
			perror("malloc申请空间失败!!!");
			return;
		}
		_capacity = 3;
		_size = 0;
	}
	void Push(DataType data)
	{
		CheckCapacity();
		_array[_size] = data;
		_size++;
	}
	void Pop()
	{
		if (Empty())
			return;
		_size--;
	}
	DataType Top() { return _array[_size - 1]; }
	int Empty() { return 0 == _size; }
	int Size() { return _size; }
	~Stack() //这个就是析构函数
	{
		if (_array)
		{
			free(_array);
			_array = NULL;
			_capacity = 0;
			_size = 0;
		}
	}
private:
	void CheckCapacity()
	{
		if (_size == _capacity)
		{
			int newcapacity = _capacity * 2;
			DataType* temp = (DataType*)realloc(_array, newcapacity *
				sizeof(DataType));
			if (temp == NULL)
			{
				perror("realloc申请空间失败!!!");
				return;
			}
			_array = temp;
			_capacity = newcapacity;
		}
	}
private:
	DataType* _array;
	int _capacity;
	int _size;
};

int main()
{
	Stack s;
	s.Push(1);
	s.Push(2);
	s.Push(3);
	s.Push(4);

	printf("%d\n", s.Top());
	printf("%d\n", s.Size());
	s.Pop();
	s.Pop();
	printf("%d\n", s.Top());
	printf("%d\n", s.Size());

	return 0;
}

下面的代码运行的结果:
运行结果
可以看到运行结果是正确的!

那么,经过上面的例子,想必你已经对构造函数和析构函数产生了一定的兴趣,也惊讶它们的便捷性(编译器可以自动调用)和好处。那么,下面我们就来深入解读这两个函数!!!

哈哈哈

3. 构造函数

3.1 概念

为了更好的引入概念,这里我会再举一个例子。

对于与下面的Date类:

class Date
{
public:
	void Init(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.Init(2024, 11, 11);
	d1.Print();

	Date d2;
	d2.Init(2020, 5, 20);
	d2.Print();

	return 0;
}

对于上面的Date类来说,每一次实例化一个对象就得调用Init函数对其进行初始化,这种行为是不是过于麻烦了,那能否再对象创建之初就将信息给设置进去呢?

这个方法就是"构造函数"!

标签:函数,int,C++,编译器,默认,Date,和析构,构造函数
From: https://blog.csdn.net/tianxiawushanu/article/details/143689663

相关文章

  • 2024年华为OD机试真题-光伏场地建设规划 -C++-OD统一考试(E卷)
    最新华为OD机试考点合集:华为OD机试2024年真题题库(E卷+D卷+C卷)_华为od机试题库-CSDN博客     每一题都含有详细的解题思路和代码注释,精编c++、JAVA、Python三种语言解法。帮助每一位考生轻松、高效刷题。订阅后永久可看,发现新题及时跟新。题目描述祖国西北部有一片大片......
  • C++ 核心代码
    C++核心代码通常指一些基础、常用的代码片段,可以用于各种C++项目中,包括输入输出、基本数据结构、算法实现等。下面是一些典型的C++核心代码示例:1.基本输入输出cppinclude<iostream>usingnamespacestd;intmain(){inta,b;cout<<"Entertwonumbe......
  • 解决 VSCode 中 C/C++ 编码乱码问题的两种方法
    解决VSCode中C/C++编码乱码问题的两种方法在中国地区,Windows系统中的cmd和PowerShell默认编码是GBK,但VSCode默认使用UTF-8编码。这种编码不一致会导致在VSCode终端中运行C/C++程序时出现乱码。以下介绍两种方法来解决这一问题。方法一:通过CodeRunner......
  • C++数学
    前言C++算法与数据结构打开打包代码的方法兼述单元测试数论:质数、最大公约数、菲蜀定理组合数学汇总计算几何博弈论曼哈顿距离与切比雪夫距离红线是哈曼顿距离,绿线是切比雪夫距离。二维曼哈顿距离转切比雪夫距离曼哈顿距离:|x1-x2|+|y1-y2|。典型应用:某个棋子只能......
  • C++ 的“活动范围”:变量的作用域和生命周期,一次搞懂!
    在C++里,变量就像是临时开的小仓库,可以用来存放各种数据。可是,不是所有变量都可以随便在哪儿都被访问到。它们都有自己的活动范围,也就是只有在特定区域才能被找到和使用。这种活动范围叫做作用域。而生命周期则是指这些变量“活着”的时间段,等生命周期结束,变量就会被自动清......
  • C++ 数据结构详解
    目录C++数据结构详解引言1.数组(Array)示例代码2.向量(Vector)示例代码3.链表(List)示例代码4.栈(Stack)示例代码5.队列(Queue)示例代码6.集合(Set)示例代码7.映射(Map)示例代码C++数据结构详解引言数据结构是计算机科学中的一个重要概念......
  • 各个语言的标准输入输出(C++,Python,Go,MATLAB)
    标准输入和输出C/C++cin,cout,getline()进行输入输出#include<bits/stdc++.h>usingnamespacestd;intmain(){//输入`1231231` inta,b,c; cin>>a>>b>>c; cout<<a<<b<<c<<endl;//输出1231231并换行(endl代表换行) //输入`......
  • C++公司人员管理系统-毕业设计源码34001
    摘  要随着信息技术的快速发展和企业规模的持续扩大,传统的手工管理方式已经无法满足现代企业对员工信息管理的需求。因此,开发一套高效、稳定且易于维护的公司人员管理系统成为了企业信息化的重要任务之一。C++作为一种成熟、高效的编程语言,以其强大的面向对象特性和广泛的......
  • 【编程语言】理解C/C++当中的指针
    指针是C/C++语言中一个非常强大且重要的概念,也是编写高效程序的基础之一。对于没有编程背景的初学者来说,理解指针可能有些难度,但通过本篇文章的介绍,相信你会对指针有一个清晰的认识。本文将从指针的基本概念、作用、代码示例、注意事项等方面,带你一步步了解指针的世界。什......
  • [C++]类和对象(上篇)
    类和对象类①类的声明与定义②成员变量的规范化1.成员变量为声明③计算类的大小1.对齐数的意义2.错题展示④成员函数的位置以及传参细节1.成员函数的位置2.传参细节this指针⑤类的6个默认成员函数1.构造函数概念特性无参构造函数与全缺省构造函数不能同时出现默......