Bootstrap

【C++】类和对象(二)

在这里插入图片描述
个人主页
在这里插入图片描述
创作不易,感谢大家的关注!

⭐一、类的默认成员函数

定义:所谓的默认成员函数,就是用户没有显式实现,而编译器会自动生成的成员函数就被称为默认成员函数。
在一个类中,在我们不写的情况下编译器会自动生成以下六个默认成员函数。其中最重要的是前四个,而取地址重载可以作为了解即可。
在这里插入图片描述

💎二、构造函数

  1. 定义:构造函数是一个特殊的成员函数,其名字与类名相同,在创建类类型对象时由编译器自动调用,保证每一个对象成员都有初始值,并在对象的生命周期内只调用一次。

  2. 特点:
    1.函数名与类名相同。
    2.没有返回值。
    3.对象实例化时系统会自动调用对应的构造函数。
    4.构造函数可以重载。

  3. 功能:
    构造函数不是用来构造对象的,它是来完成对象初始化的。

  4. 注意事项:
    1.如果类中没有显式定义构造函数,那么C++编译器会自动生成一个无参的默认构造函数,一旦用户定义则编译器将不再生成。
    2.无参构造函数、全缺省构造函数和当我们不写构造时编译器默认生成的构造函数,都被称为默认构造函
    数。但是这三个函数有且仅有一个存在,不能同时存在。

演示代码:

#define _CRT_SECURE_NO_WARNINGS 1

#include<iostream>

using namespace std;

class Date
{
public:

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

⏱️三、析构函数

  1. 概念:与构造函数的功能相反,析构函数并不是完成对对象本身的销毁,C++规定对象在销毁时会自动调用析构函数,完成对象中资源的清理释放工作。
  2. 特点:
    1.析构函数名是在类名前加上字符 ~。
    2.无参数和无返回值。
    3.⼀个类只能有⼀个析构函数。若未显式定义,系统会自动生成默认的析构函数。
    4.对象生命周期结束时,编译器会自动调用析构函数。
  3. 功能:
    完成对象中资源的清理释放工作。
  4. 注意事项:
    1.我们不写编译器自动生成的析构函数对内置类型成员不做处理,自定义类型成员会调用他的析构函数。
    2.如果类中没有申请资源时,析构函数可以不写,直接使用编译器自动生成的默认析构函数。
    (注:在有资源申请时,一定要自己写析构函数,否则会造成资源泄露)
    3.一个局部域的多个对象,C++规定后定义的先析构。

代码演示:

#define _CRT_SECURE_NO_WARNINGS 1

#include<iostream>

using namespace std;

class Time
{
public:
	//析构函数
	~Time()
	{
		cout << "~Time()" << endl;
	}
private:
	int _hour;
	int _minute;
	int _second;
};

class Date
{
public:
private:
	int _year;
	int _month;
	int _day;
	// 自定义类型
	Time _t;
};

int main()
{
	Date a;
	return 0;
}

🏝️ 四、拷贝构造函数

  1. 概念:拷贝构造函数是通过一个对象来初始化另一个对象,也是一个特殊的构造函数。
  2. 特点:
    1.拷贝构造函数是构造函数的⼀个重载。
    2.拷贝构造函数的参数只有⼀个且必须是类类型对象的引用,使用传值方式是编译器会产生报错,因为在语法逻辑上会引发无穷递归。
    3.C++规定自定义类型对象在进行拷贝行为时必须调用拷贝构造。
  3. 注意事项:
    若未显式定义拷贝构造时,编译器会自动生成拷贝构造函数。而自动生成的拷贝构造对内置类型成员变量会完成值拷贝或浅拷贝(⼀个字节⼀个字节的拷贝),在对自定义类型成员变量时会调用它本身的拷贝构造。

代码演示:

#define _CRT_SECURE_NO_WARNINGS 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 Print()
	{
		cout << _year << "年" << _month << "月" << _day << "日" << endl;
	}
private:
	int _year;
	int _month;
	int _day;
};

int main()
{
	Date d1(2024, 7, 20);
	//用已存在的对象d1来初始化对象d2
	Date d2(d1); 
	d1.Print();
	d2.Print();
	return 0;
}

🎄五、赋值运算符重载

  1. 定义:C++为了增强代码的可读性引入了运算符重载,允许我们通过运算符重载的形式来指定新的含义。

  2. 特点:
    1.运算符重载是具有特殊名字的函数,它的名字是由operator和后面要定义的运算符共同构成,具有其返回类型和参数列表以及函数体。
    2.运算符重载以后,其优先级和结合性与对应的内置类型运算符保持⼀致。

  3. 3.如果⼀个重载运算符函数是成员函数,则它的第⼀个运算对象默认传给隐式的this指针,因此运算符重载作为成员函数时,参数比运算符对象少⼀个。

  4. 注意事项:
    1.不能通过连接语法中没有的符号来创建新的操作符:比如operator@。
    2.重载操作符至少有⼀个类类型参数,不能通过运算符重载改变内置类型对象的含义。
    3.sizeof 、:: 、.* 、?: 、. 这5个运算符不能重载。
    4.重载++运算符时,有前置++和后置++,因此.C++规定,后置++重载时,增加⼀个int形参,跟前置++构成函数重载,方便区分。
    5.重载<<和>>时,需要重载为全局函数,因为重载为成员函数时,this指针默认抢占了第⼀个形参位置,而第一个形参的位置为左侧运算符对象。而重载为全局函数时就可以把ostream/istream放到第⼀个形参位置。

🏠六、取地址运算符重载

取地址运算符重载分为普通取地址运算符重载和const取地址运算符重载,⼀般这两个函数由编译器自动生成的就足够我们使用了,不需要额外去显式实现。

🎉const成员

  1. 定义:将const修饰的成员函数就称为const成员函数,const修饰成员函数放到成员函数参数列表的后面。

  2. 功能:const实际修饰该成员函数隐含的this指针,表明在该成员函数中不能对类的任何成员进行修改。

  3. 下面有这么几个问题:
    1.const成员能够调用非const成员的函数吗?
    2.非const成员可以调用const成员函数吗?
    3.const成员函数内可以调用其他的非const成员函数吗?
    4.非cosnt成员函数内可以调用其他的cosnt成员函数吗?

我们先来揭晓答案:
1.不可以 2.可以 3.不可以 4.可以

下面对上述问题进行阐释:
1.非const成员函数,即成员函数的this指针没有被const所修饰,当我们传入一个const修饰的对象时,被一个非const修饰的成员函数所接受,属于权限放大,因此函数调用失败。
2.const成员函数,即成员函数的this指针被const所修饰,当我们传入一个非const修饰的对象时,被一个const修饰的成员函数所接受,属于权限缩小,函数调用成功。
3…在一个被const所修饰的成员函数中调用其他没有被const所修饰的成员函数,属于权限的放大,因此函数调用失败。
4.在一个没有被const所修饰的成员函数中调用其他被const所修饰的成员函数,属于权限缩小,函数调用成功。

总结:权限可以被放大,但不能被缩小,否则就会出现报错。

;