【c++】默认成员函数:构造函数|拷贝构造函数

目录

一:前言

 二:默认成员函数

三:构造函数

一:构造函数概念

二:构造函数的特性

三:构造函数实例 

四:注意

五:默认构造函数 

 四:拷贝构造函数

 一:拷贝构造函数的特性

二:默认实参拷贝函数

五:总结


一:前言

本片博客为大家讲解构造函数|析构函数|拷贝构造函数在c++中的作用。

 二:默认成员函数

类中有六个默认成员函数:

我们一一来学习这些成员函数。

如果我们需要初始化,构造函数会给我们带来意想不到的结果。

清理也一样,析构函数就很good。

三:构造函数

一:构造函数概念

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

 构造函数是i特殊的成员函数,需要注意的是构造函数虽然名称叫构造,但构造函数的主要对象不是开空间创造对象而是初始化对象

二:构造函数的特性

  1.  函数名与类名相同。
  2.  无返回值。
  3.  对象实例化时编译器自动调用对应的构造函数。
  4.  构造函数可以重载。 

三:构造函数实例 

古板概念我们就不细细研究了,我们上代码研究,自然而然的就懂了。

代码演示:Date.cpp 

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(2022, 7, 5);
 d1.Print();
 Date d2;
 d2.Init(2022, 7, 6);
 d2.Print();
 return 0;
}

对于Date类,可以通过 Init 公有方法给对象设置日期,但如果每次创建对象时都调用该方法设置信息,未免有点麻烦,那能否在对象创建时,就将信息设置进去呢?

这样子就很麻烦,我们每次传参都要调用函数,所以我们的c++神,本贾尼大佬,就创造了构造函数,我们不调用,直接给赋值。

代码演示:(带参构造)

#include<iostream>
using namespace std;
class Date
{
public:
	 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(1998,10,2);
	d1.Print();
	Date d2(1996,12,3);
	d2.Print();
	return 0;
}

终端显示:

这样子就很完美,我们不用在写初始化函数,我们每次直接在类赋值就可以。

如图这是一个带参构造。我展示无参构造。

代码演示:

class Date
{
public:
	Date()
	{
		_year = 1;
		_month = 0;
		_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;
};

// Date f(); 函数声明
int main()
{
	Date d1;
	d1.Print();

	Date d2(2023, 10, 19);
	d2.Print();

	return 0;
}

终端显示:

 如上图终端显示:

不给参数就会调用无参构造函数,给参数就会调用带参构造函数。

这个带参构造就是全缺省构造函数,也要记住全缺省的规则,以及半缺省的要求。

四:注意

1:如果通过无参构造函数创建对象时,对象后面不用跟括号,否则就成了函数声明

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

	Date d2(2023, 10, 19);
	d2.Print();

	return 0;
}

2:如果你没有定义构造函数,编译器会自动帮助你生产一个无参的默认构造函数

class Date
{
public:
	

	//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;
};

// Date f(); 函数声明
int main()
{
	Date d1;
	d1.Print();
	return 0;
}

终端显示:

五:默认构造函数 

无参构造函数,全缺省构造函数,自动生成的构造函数都称为 默认构造函数 

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


class Date
{
public:
	Date()
	{
		_year = 1;
		_month = 1;
		_day = 1;
	}
	Date(int year=1999 , int month=2 , int day=2 )
	{
		_year = year;
		_month = month;
		_day = day;
	}
	void Print()
	{
		cout << _year << "-" << _month << "-" << _day << endl;
	}

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

// Date f(); 函数声明
int main()
{
	Date d1;
	d1.Print();
	return 0;
}

 【显示报错】

虽然语法上允许他们存在,但是到编译器去调用就不可以。

强推全缺省构造函数和半缺省构造:

class Date
{
public:
	Date(int year=1999 , int month=2 , int day=2 )
	{
		_year = year;
		_month = month;
		_day = day;
	}
	void Print()
	{
		cout << _year << "-" << _month << "-" << _day << endl;
	}

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

// Date f(); 函数声明
int main()
{
	Date d1(2003,2,3);
	d1.Print();
	Date d2(2003, 2);
	d2.Print();
	return 0;
}

终端显示:

这样好处还是很多,如果需要多次使用构造函数,就不需要每次都传参,传常需要使用的便可,增加代码的可读性,提高效率。

 四:拷贝构造函数

拷贝构造函数:只有单个形参,该形参是对本类类型对象的引用(一般常用const修饰),在用已存在的类类型对象创建新对象时由编译器自动调用。

 一:拷贝构造函数的特性

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

2. 拷贝构造函数的参数只有一个且必须是类类型对象的引用,使用传值方式编译器直接报错,因为会引发无穷递归调用。所以我们必须使用引用。

 拷贝构造函数原型:

类名 (const 类型 & 形参)

直接存放类里面public域中。

繁琐 其实就是在帮你拷贝一个相同的供呢使用,不多说了,上代码:

class Date
{
public:
	Date(int year , int month , int day)
	{
		_year = year;
		_month = month;
		_day = day;
	}
	/*Date d2(d1);*///拷贝构造函数
	Date(const Date  & d)
	{
		_year = d._year;
		_month = d._month;
		_day = d._day;
	}
	void Print()
	{
		cout << _year << "-" << _month << "-" << _day << endl;
	}

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


int main()
{
	Date d1(2003,2,3);
	Date d2(d1);
	d1.Print();
	d2.Print();
	return 0;
}

终端显示:

非常好我们完美的拷贝下来了,

注意:前面提到我们必须使用引用进行传参,实参传递有指针传参,传值,为什么偏偏使用引用呢? 

    在调用拷贝构造函数 ,先传参,(如果传值传参),又形成新的拷贝构造,形成无穷递归,我们了解引用的话,引用就跟好的实现,又不浪费内存,也不需要新的变量,在原基础上进行操作,然后我们在使用const便跟好的利用引用。

二:默认实参拷贝函数

 若未显式定义,编译器会生成默认的拷贝构造函数。 默认的拷贝构造函数对象按内存存储按
字节序完成拷贝,这种拷贝叫做浅拷贝,或者值拷贝。

class Date
{
public:
	Date(int year , int month , int day)
	{
		_year = year;
		_month = month;
		_day = day;
	}
	/*Date d2(d1);*///拷贝构造函数
	//Date(const Date  & d)
	//{
	//	_year = d._year;
	//	_month = d._month;
	//	_day = d._day;
	//}
	void Print()
	{
		cout << _year << "-" << _month << "-" << _day << endl;
	}

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


int main()
{
	Date d1(2003,2,3);
	Date d2(d1);
	d1.Print();
	d2.Print();
	return 0;
}

让我们看看终端:

so 酷,这就是默认拷贝了,我没有调用拷贝函数,说明c++功能是真的多呀,基本都会个出默认值,我感觉就好像不能使其他变量成为野的一样。

注意:类中如果没有涉及资源申请时,拷贝构造函数是否写都可以;一旦涉及到资源申请时,则拷贝构造函数是一定要写的,否则就是浅拷贝。 

五:总结

构造函数 :

对于构造函数,我建议如果需要使用初始化,就去使用全缺省或者半缺省,

虽然构造函数是成员函数,编译器会自动帮助我们生成默认构造函数,但是我们还是自己去初始化,虽然方便 但至少逻辑清晰,不会因为初始化的问题乱了方向。

拷贝构造函数:

 如果使用拷贝构造函数,调用的时候一定要用引用!!!!!不然会无穷递归,死循环,

也会默认拷贝,但不建议,

由于水平有限,本片博客如果有错误或者不足之处,希望读者纠正,感谢阅读。 

  • 36
    点赞
  • 50
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值