C++类和对象(中)

在这里插入图片描述

✨Blog:🥰不会敲代码的小张:)🥰
🉑推荐专栏:C语言🤪Cpp😶‍🌫️数据结构初阶💀
💽座右铭:“記住,每一天都是一個新的開始😁😁😁
💀本章内容:《C++类和对象(中)》的介绍✨

前言

上期我们讲了C++类和对象(上)

类的6个默认成员函数

如果一个类中什么成员都没有,简称为空类。
空类中真的什么都没有吗?并不是,任何类在什么都不写时,编译器会自动生成以下6个默认成员函数。
在这里插入图片描述
用白话来说就是:我们不写,编译器会自己生成

构造函数

  1. 函数名与类名相同。
  2. 无返回值。
  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;
	}
private:
	int _year;
	int _month;
	int _day;
};

如果类中没有显示定义构造函数,则C++编译器会自动生成一个无参默认构造函数,内置类型不做处理自定义类型会去调用他的默认构造
如何理解上面这句话呢,下面我们来看一段代码
内置类型:
在这里插入图片描述
自定义类型:
在这里插入图片描述
1.一般情况下,有内置类型成员,就需要自己写构造函数,不能用编译器自己生成
2.如果都是自定义类型成员,可以考虑让编译器自动生成构造函数
如:OJ题,用两个栈实现队列
但是归根结底最开始的自定义类型类型还是自己写了构造函数
结论:
1.一般情况下,构造函数都需要自己写
2.什么情况下不需要写呢?
a.内置类型成员都有缺省值,且初始化符合我们的要要求
b.全是自定义类型,且这些类型都定义了默认构造

可以在类型声明的时候给缺省值:
如果我们没有显示传递值,那么编译器就会使用默认缺省值,相当于备胎
在这里插入图片描述

析构函数

析构函数:与构造函数功能相反,析构函数不是完成对对象本身的销毁,局部对象销毁工作是由编译器完成的。而对象在销毁时会自动调用析构函数,完成对象中资源的清理工作。

  1. 析构函数名是在类名前加上字符 ~。
  2. 无参数无返回值类型。
  3. 一个类只能有一个析构函数。若未显式定义,系统会自动生成默认的析构函数。注意:析构函数不能重载
  4. 对象生命周期结束时,C++编译系统系统自动调用析构函数。

这里我们只演示自定义类型是不是会去调用它自己的析构:
在这里插入图片描述

  1. 一般情况下,有动态内存申请的,就需要显示写析构函数释放资源
  2. 没有动态资源申请,不需要写析构
  3. 需要释放的对象成员都是自定义类型,不需要写析构

拷贝构造

在现实生活中,可能存在一个与你一样的自己,我们称其为双胞胎

  1. 拷贝构造函数是构造函数的一个重载形式。
  2. 拷贝构造函数的参数只有一个且必须是类类型对象的引用,使用传值方式编译器直接报错,因为会引发无穷递归调用。
    在这里插入图片描述

C++规定内置类型传参是直接拷贝,自定义类型传参是先调用拷贝构造完成拷贝。
内置类型:我们不写编译器自己生成,内置类型成员完成值拷贝/浅拷贝
在这里插入图片描述
**自定义类型:**自定义类型成员会调用它的拷贝构造
在这里插入图片描述

如果要拷贝构造的函数中有malloc出来的空间,需要自己定义深拷贝,否则会指向同一块空间,析构函数就会调用两次,程序就会崩,另外一个问题就是,一个修改,会影响另外一个。

运算符重载

日期-日期//有意义
日期+日期//没意义
是否要运算符重载,取决这个运算符对这个类是否有意义

  1. 操作符有几个操作数,重载函数就有几个参数
  2. operator后加操作符
    .* :: sizeof ?: . 这五种运算符不能构成重载
class Date
{
public:
	Date(int year, int month, int day)
	{
		_year = year;
		_month = month;
		_day = day;
	}
	bool operator<(const Date& d)
	{
		if (_year < d._year)
		{
			return true;
		}
		else if (_year == d._year && _month < d._month)
		{
			return true;
		}
		else if (_year == d._year && _month == d._month && _day < d._day)
		{
			return true;
		}
		else
		{
			return false;
		}
	}

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

int main()
{
	Date d1(2023, 2, 3);
	Date d2(2024, 2, 3);
	bool ret = d1 < d2;//自定义类型比较大小,会去调用运算符重载
	cout << ret << endl;
	return 0;
}

iostream头文件包含ostream和istream,ostream包含operator自定义类型运算符重载,而cout就是调用operator<<函数重载自动匹配内置类型,我们之所以可以使用内置类型比较大小,是因为内置类型是库里面已经实现的。

赋值重载

已经存在的两个对象之间复制拷贝
编译器自己生成的赋值重载,只能完成浅拷贝,如果有malloc出来的对象,需要自己写赋值重载。
在这里插入图片描述
默认生成的赋值重载跟拷贝构造是一样的
1.内置类型———值拷贝/浅拷贝
2.自定义类型成员会去调用它的赋值重载

取地址重载

在平常内置类型可以直接使用取地址运算符,但是自定义类型不可以,不过系统会自动生成默认函数,平时默认的就足够使用。
在这里插入图片描述

const成员

将const修饰的“成员函数”称之为const成员函数,const修饰类成员函数,实际修饰该成员函数隐含的this指针,表明在该成员函数中不能对类的任何成员进行修改。

void Print()const
==
void Print(const Date*this)
但是this指针是隐式的,不能显示修改,所以直接在括号后面加上const。

bool operator==(const Date& d) const//修饰的是*this
{
	return _year == d._year
		&& _month == d._month
		&& _day == d._day;
}

加上const以后,普通对象和const对象都可以掉用,普通对象调用加上const函数,权限缩小
权限缩小可以,但是不能权限放大。

如果没有加上const,而实例化对象是const,则不能正常调用,因为权限可以平移,可以缩小,但是不能放大。
在这里插入图片描述
结论:

  1. 要修改的对象成员函数不能加const
  2. 只要成员函数内部不修改,都应该加上const
    因为这样const对象和普通对象都可以调用
  • 35
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 10
    评论
评论 10
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

不会敲代码的小张:)

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值