14.2 构造函数详解、explicit与初始化列表

一:构造函数

在类中,有一种特殊的成员函数,他的名字和类名相同,我们在创建类对象的时候,这个特殊的成员函数就会被系统自动调用。这个成员函数,就叫"构造函数"。因为构造函数会被系统自动调用,所以我们可以简单的理解成:构造函数的目的就是初始化类对象的数据成员。

class time{
public:
	int hour;
	int minute;
	int second;
public:
	time(int tmphour,int tmpmin, int tmpsec){
		hour = tmphour;		
		minute = tmpmin;
		second = tmpsec;
		cout << "调用了三个参数的构造函数" << endl;
	}
public:	time(){
		hour = 12;
		minute = 13;
		second = 52;
		cout << "调用了空的构造函数" << endl; 
	}
public:	time(int number){
		hour = number;
		minute = 13;
		second = 52; 
		cout << "调用了单参数的构造函数" << endl;
}
public:
	time(int tmphour,int tmpmin, int tmpsec=52){
		hour = tmphour;		 
		minute = tmpmin;
		second = tmpsec;
	};

1、构造函数没有返回值,这也是构造函数的特殊之处。
2、不可以手工调用构造函数,否则编译就会出错。
3、正常情况下,构造函数应改被声明为public,因为我们创建一个对象时,系统要替我们调用构造函数,这说明构造函数它是一个public函数,才能被系统(外界)调用。因为类缺省的成员是私有成员,所以我们必须说明构造函数是一个public函数,否则无法直接创建该类的对象。
4、构造函数中如果有多个参数,则我们创建对象的时候也要带上这些参数。

time mytime = time(12,13,52);    创建类对象
time mytime2(12,13,52);
time mytime3 = time{12,13,52};
time mytime4{12,13,52};
time mytime5 = {12,13,52};

二:多个构造函数

一个类中可以有多个构造函数,就可以为类对象的创建提供多种初始化方法。参数的个数和参数的类型不一样即可。

time mytime1 = time();    创建类对象
time mytime2;
time mytime3 = time{};
time mytime4{};
time mytime5 = {};

//对象拷贝
time mytime6;可以调用构造函数 

如下四个对象并没有调用传统意义上的构造函数,后续笔记记载,他们调用的实际上是拷贝构造函数。
time mytime7 = mytime6;
time mytime8(mytime6);
time mytime9{mytime6};
time mytime10 ={mytime6};

三:函数默认参数

1、默认值只能放在函数声明中,除非该函数没有函数声明。
2、在具有多个参数的函数中指定默认值时,默认参数都必须出现在不默认参数的右边,一旦某个参数开始指定默认值,它右边的所有参数必须指定默认值。

time mytime11 = time(12, 13);  //创建类对象
time mytime12(12, 13);
time mytime13 = time{12, 13};
time mytime14{12, 13};
time mytime15 = {12, 13};

四:隐式转换和explicit

编译系统,在私下干了很多我们所不知道和不了解的事。
time mytime40 = 14 编译系统肯定有一个行为,把14这个数字转换成为一个time类型,调用了单参数的构造函数。
time mytime = (12,13,14,15,16); 调用了单参数的构造函数。

void func1(time t1)
{
}
func1(16);

time mytime16 = {16};  //这个写法我们认为正常,带一个参数16,可以让系统明确的知道调用了哪个构造函数,隐式类型转换。
time mytime17 = 16;    //含糊不清的写法,就存在临时对象的隐式转换。

是否可以强制系统,明确要求构造函数不能做隐式类型转换呢?
可以,如果构造函数声明中带有explicit,则这个构造函数只能用于初始化和显式类型转换。

class time1{
	public:
		int hour;
		int minute;
		int second;
	public:
		explicit time(int tmphour,int tmpmin, int tmpsec){
			hour = tmphour;		
			minute = tmpmin;
			second = tmpsec;
			cout << "调用了三个参数的构造函数" << endl;
	}
}; 

time1 mytime = time1(12,13,52);    
time1 mytime2(12,13,52);
time1 mytime3 = time1{12,13,52};
time1 mytime4{12,13,52};
time1 mytime5 = {12,13,52};    //隐式类型转换。这个出现问题。

对于单参数的构造函数,一般都声明为explicit,除非你有特别原因。explicit也可以用于无参或者多个参数的构造函数。

五:构造函数初始化列表

class time2{
	public:
		int hour;
		int minute;
		int second;
	public:
		 time(int tmphour,int tmpmin, int tmpsec)
		 :hour(tmphour),minute(tmpmin),second(tmpsec)
		{
			cout << "调用了三个参数的构造函数" << endl;
		}
};

<1>显得专业,高大上。
<2>效率上更高。(对于类类型的成员变量,少调用一次甚至几次该成员变量相关类的各种特殊成员函数)

避免写出下面的代码:

Time::Time(int hour, int minute, int second) : Hour(hour), Minute(Hour), Second(Minute)
{
	cout << "Time被初始化了" << endl;
}

成员变量的给值撒混徐并不是一句初始化列表的从左到右的顺序,而是依据类定义中成员变量的定义顺序(从上到下的顺序)。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值