C++语言— 类中的构造函数和拷贝构造函数

             构造函数

在说这个之前我想问一个问题,如果成员变量是私有的,我们怎么初始化这些私有的成员变量?


其实这就是构造函数的存在的理由,因为这个成员变量为私有的,要对它们进行初始化,必须用一个
公有成员函数来进行。同时这个函数应该有且仅在定义对象时自动执行一次,这时调用的函数称为构
造函数(constructor) 


下面就是构造函数的特征:
1.函数名与类名相同。
2.无返回值。
3.对象构造(对象实例化)时系统自动调用对应的构造函数。
4.构造函数可以重载。
5.构造函数可以在类中定义,也可以在类外定义。
6.如果类定义中没有给出构造函数,则C++编译器自动产生一个缺省的构造函数,但只要我们定义了一个
构造函数,系统就不会自动生成缺省的构造函数。
7.无参的构造函数和全缺省值的构造函数都认为是缺省构造函数,并且缺省的构造函数只能有一个。
下面我们举个例子:

定义一个Date类,在它尝试使用一下构造函数。

class Date
{
public:
	// 1.无参构造函数
	Date()
	{}

	// 2.带参构造函数
	Date(int year, int month, int day)
	{
		cout << "我定义的构造函数成功运行了" << endl;
		_year = year;
		_month = month;
		_day = day;
	}
	void Display()
	{
		cout << _year << " " << _month << " " << _day << endl;
	}
private:
	int _year;
	int _month;
	int _day;
};

void TestDate1()
{
	Date d1;               // 调用无参构造函数
	d1.Display();
}
int main()
{
	TestDate1();
	system("pause");
	return 0;
}

由于并未对类中的成员进行初始化,也就是我们调用了无参的构造函数,不出所料出现的是随机值。



现在我们试试有参的构造函数:

class Date
{
public:
	// 1.无参构造函数
	Date()
	{}

	// 2.带参构造函数
	Date(int year, int month, int day)
	{
		cout << "我定义的构造函数成功运行了" << endl;
		_year = year;
		_month = month;
		_day = day;
	}
	void Display()
	{
		cout << _year << " " << _month << " " << _day << endl;
	}
private:
	int _year;
	int _month;
	int _day;
};

void TestDate1()
{
	Date d2(2015, 1, 1);   // 调用带参的构造函数
	d2.Display();
}
int main()
{
	TestDate1();
	system("pause");
	return 0;
}
因为我们知构造函数是可以重载的,所以我们这次使用有参的构造函数。结果应该是我首先输出一段话
,然后依次打印出成员变量,我们来看看:


还有一种缺省参数的构造函数,我们分别来看看他们的结果:

class Date
{
public:
	// 3.缺省参数的构造函数
	Date(int year = 2000, int month = 1, int day = 1)
	{
		cout << "我调用成功了" << endl;
		_year = year;
		_month = month;
		_day = day;
	}

	// 4.半缺省参数的构造函数(不常用)
	Date(int year, int month = 1)
	{
		_year = year;
		_month = month;
		_day = 1;
	}
	void Display()
	{
		cout << _year << " " << _month << " " << _day << endl;
	}
private:
	int _year;
	int _month;
	int _day;
};

void Test()
{
	Date d1;               // 调用缺省构造函数
	d1.Display();
}
int main()
{
	Test();
	system("pause");
	return 0;
}
看看结果,因为它早早地已经有自己的值了,所以就算没有参数也没有关系



class Date
{
public:
	// 3.缺省参数的构造函数
	Date(int year = 2000, int month = 1, int day = 1)
	{
		cout << "我调用成功了" << endl;
		_year = year;
		_month = month;
		_day = day;
	}

	// 4.半缺省参数的构造函数(不常用)
	Date(int year, int month = 1)
	{
		_year = year;
		_month = month;
		_day = 1;
	}
	void Display()
	{
		cout << _year << " " << _month << " " << _day << endl;
	}
private:
	int _year;
	int _month;
	int _day;
};
//这里注意半缺席的构造函数,参数从前往后可以缺省,但是不能从最后一位开始缺省
void Test()
{
	Date d2(2015,3,2);   // 调用缺省构造函数
	d2.Display(); 
}
int main()
{
	Test();
	system("pause");
	return 0;
}



备注:若缺省参数声明和定义分离,则可以在声明或定义中给默认参数。



          拷贝构造函数

创建对象时使用同类对象来进行初始化,这时所用的构造函数称为拷贝构造函数(Copy Constructor)
,拷贝构造函数是特殊的构造函数。

特征:

1.拷贝构造函数其实是一个构造函数的重载。

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

3.若未显示定义,系统会默认缺省的拷贝构造函数。缺省的拷贝构造函数会,依次拷贝类成员进行初始化



举个Date类,练习一下拷贝构造。

class Date
{
public:
		Date(int year, int month , int day)
		{
			cout << "构造调用成功了" << endl;
			_year = year;
			_month = month;
			_day = day;
		}
	// 拷贝构造函数
	Date(const Date& d)
	{
		cout << "拷贝构造被调用了" << endl;
		_year = d._year;
		_month = d._month;
		_day = d._day;
	}
	void Display()
	{
		cout << _year << " " << _month << " " << _day << endl;
	}
private:
	int _year;
	int _month;
	int _day;
};

void TestDate1()
{
	Date d1(2017,3,6);

	// 下面两种用法都是调用拷贝构造函数,是等价的。
	Date d2(d1);    // 调用拷贝构造函数
	Date d3 = d1;    // 调用拷贝构造函数
	d2.Display();
	d3.Display();
}
int main()
{
	TestDate1();
	system("pause");
	return 0;
}
这里我们可以看到调用一次构造函数,调用两次拷贝构造,然后让我们看看结果吧。



拷贝构造函数特征第二条,拷贝构造函数的参数必须使用引用传参,使用传值方式会引发无穷递归调用。

这个为什么不行呢?

思考一下,如果我们使用值传递,传参的时候是不是需要创建一个新的形参,而这个新的形参就值本身,
也就是自身的一个拷贝,然后呢,又调用了拷贝构造,然后就无穷递归了。

还有一个问题。




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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值