C++--类与对象(中)--类的6中默认成员函数--构造函数--析构函数--拷贝构造函数

引入

如你所见,我下面写的这行代码就是一个类,可是你想想类能这么简单吗?答案肯定是:不是,因为类将很多的函数设置成了默认函数,你是看不见的,所以看起来也就是比较简单,关于类我们有6类默认函数,每一种都有自己独有的功能,如下:

class Date{}

在这里插入图片描述
上面是主要的分类,下面我们分开仔细讲解

构造函数

构造函数就是对已经创建的函数进行初始化,

概念

下面这个就是我们简单的构造了一个简单的日期类的函数.分为公有的和私有类
内部的以Date开头的这种函数,这种函数就叫做构造函数

class Date{

public:
	//构造函数可以重载
	//无参:默认构造
	//编译器自动生成的也是默认构造

	Date(){
		
		cout << "Date()" << endl;
	}

	//====!!!上面和下面这两中默认构造只能存在一种,不能多次出现
	//====无参构造或者全缺省构造

	//全缺省	也是一种默认的构造
	Date(int year=1, int month=1, int day=1){
		
		_year = year;
		_month = month;
		_day = day;
		cout << "Date(int,int,int)" << endl;
	}

	Date(int  year, int month, int day, int num){
		
		_year = year;
		_month = month;
		_day = day;
		cout << "Date(int,int,int,int)" << endl;
	}

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

下面的式子是对于上面函数的一个简单的使用情况,下面写的有些方式是错误的,大家注意看我的注释,不要搞混了

void test3(){

	Date d;		//调用无参构造
	
	//调用带参数的构造(自动调用)
	Date d1(1998, 12, 25);
	Date d2(1999, 06, 28);		//参数列表中对应的个数和类型要一致,不然就会报错找不到

	Date d3(2019, 20, 25, 35);//编译器会自动对你定义的函数类型和
							 // 变量的数目自动定义你要调用的函数
	//不能显示调用函数
	d.Date(2020, 2, 2);		//报错

	//不是调用无参的构造,而是声明一个函数
	//函数名:d4
	//参数列表: 空
	//返回值:Date
	Date d4();		//对于无参数的直接是 Date d4;即可
}

特性

1.构造函数就是对已经创建好的函数进行进一步的初始化

2.在没有参数传入的时候或者是由编译器自动生成的时候都是默认构造,是不进行显示

3.全缺省也是一种默认构造,只能存在一个默认构造,不能多次出现

4.在调用带参构造的时候,在参数列表中对应的个数和类型要一致,不然就会报错

5.对于无参数的调用的时候,不需要加(),这一点在上面这个代码的最下面有示例,大家自己看

6.函数名与类名相同

7.无返回值

8.对象实例化时编译器自动调用对应的构造函数。

9.构造函数可以重载

10.无参的构造函数和全缺省的构造函数都称为默认构造函数,并且默认构造函数只能有一个。注意:无参构造函数、全缺省构造函数、我们没写编译器默认生成的构造函数,都可以认为是默认成员函数。

析构函数

概念

对于析构函数,不是对其中的对象进行销毁,而是对其中资源的一个清理
1.析构函数在类名前面会"~"

2.无参数无返回值

3.一个对应的类只有一个析构函数,如果你没有进行定义的话,系统会自动生成析构函数

4.在对象的生命周期结束的时候,C++编译器会自动调用析构函数来对类的内部进行清理

下面这个代码就是顺序表进行析构函数的实现:

typedef int DataType;
class SeqList
{
public:
	SeqList(int capacity = 10)
	{
		_pData = (DataType*)malloc(capacity * sizeof(DataType));

		_size = 0;
		_capacity = capacity;
	}
	//析构函数
	//对象销毁的时候,编译器自动调用析构,完成资源的清理
	~SeqList()		//这个成员函数内部就是清理的操作,你仔细阅读可以看出来
	{
		if (_pData) 
		{
			free(_pData); // 释放堆上的空间
			_pData = NULL; // 将指针置为空
			_capacity = 0;
			_size = 0;
			cout << "~SeqList" << endl;
		}
	}

private:
	int* _pData;
	size_t _size;
	size_t _capacity;
};

对应的实现调用代码

void test5(){
	//Date d(2020, 2, 3);

	//动态开辟一个对应的空间,可以存放10个元素
	//将对应的首地址保存在_pData中
	SeqList sq(10);		//这里匹配的空间没有保存在顺序表中,是将空间开辟在堆上,然后用指针进行调用

	cout << sizeof(sq) << endl;
	
}

当你在这个类里面如果没有找到析构函数的时候,那就是编译器自己默认生成了一个析构函数,如果找到了,编译器就会自动调用自定义成员的析构函数完成对自定义成员的清理!

特性

1.在没有显示析构函数的时候,编译器会自动生成默认的析构结构
2.编译器会自动调用自定义成员的析构函数,完成自定义成员的清理
3.在相关的这个对象被销毁的时候,编译器会进行自动调用,完成清理

拷贝构造函数

概念

拷贝构造函数是对其中的一个成员函数进行拷贝,但是对其中如果含有指针的指向都没有发生变化,就是创建一个一摸一样的!
如下面代码的中间:Date(const Date& d)

class Date{

public:
	
	Date(int year = 1, int month = 1, int day = 1){

		_year = year;
		_month = month;
		_day = day;
		cout << "Date(int,int,int)" << endl;
	}
	//如果不显示定义拷贝构造,编译器会自动生成拷贝构造
	Date(const Date& d){		//如果这里没有加取地址的符号的时候, 它只会
								//无限的进行拷贝调用下去,而一致无法对其中的值进行拷贝
		
		_year = d._year;
		_month = d._month;
		_day = d._day;

		cout << "参数的拷贝" << endl;		//在这里添加一个检验,看是否会直接调用拷贝的这个函数
	}

	Date(int  year, int month, int day, int num){

		_year = year;
		_month = month;
		_day = day;
		cout << "Date(int,int,int,int)" << endl;
	}

private:
	int _year;
	int _month;
	int _day;
};
void test(){
	
	Date date(2020, 02, 20);
	//创建拷贝构造,创建copy对象,内容和date完全一致
	Date copy(date);
}

特性

1.拷贝构造函数是构造函数的一个重载形式.

2.拷贝构造函数的参数只有一个且必须使用引用传参,使用传值方式会引发无穷递归调用.

3 若未显示定义,系统生成默认的拷贝构造函数默认的拷贝构造函数对象按内存存储按字节序完成拷贝,这种拷贝我们叫做浅拷贝,或者值拷贝.

4.如果不显示定义拷贝构造,编译器会自动生成拷贝构造

5.拷贝构造必须加**&**符号,如果没有加会无限循环下去,使拷贝无法实现

6.它只能应用于一些简单的拷贝方式上,不会拷贝对象的资源!对于一些有资源的类,必须进行显示定义,比如如果其中一个个含有free的操作符,而拷贝的地址又是指向同一个区域的,这样的话free操作就会执行多次,造成代码错误,所以对于这种有资源的,我们就要单独拎出来进行操作

今天的只是有点复杂,大加可以仔细看看,多敲敲代码实现一下!!!就可以了!!!加油!!!

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值