目录
一,初始化列表
1.初始化列表的使用
2.初始化列表的特点
3.必须要使用初始化列表的场景
二,单参数构造函数的隐式类型转换
1.内置类型的隐式类型转换
2. 自定义类型的隐式类型转换
3.多参数构造函数的隐式类型转换
4.当你不想要发生隐式类型转换时便可以使用explicit关键字。
一,初始化列表
1.初始化列表的使用
初始化列表是Cpp语法中新加的一个语法。作用是初始化类里面的一些成员。使用方式如下:
class Date
{
Date()
:_year(0)
,_month(0)
,_day(0)
{
}
private:
int _year;
int _month;
int _day;
};
1.以冒号开始。
2.以逗号分割各个成员。
3.以括号里面放入相匹配的值来显示初始化成员。
执行初始化列表以后结果如下:
2.初始化列表的特点
1.初始化列表是成员定义的地方,不管有没有写初始化列表,成员都会被初始化。
比如,当我把_month成员的初始化给屏蔽掉了以后:
class Date
{
public:
Date()
:_year(0)
//,_month(0)
,_day(0)
{
}
private:
int _year;
int _month;
int _day;
};
int main()
{
Date a1;
return 0;
}
结果:
2. 初始化列表的执行顺序是按照声明的顺序来执行的。比如以下代码:
class A
{
public:
A()
:_a1(1)
,_a2(_a1)
{
}
void print()
{
cout << "_a1:"<<_a1 << endl;
cout << "_a2:"<<_a2 << endl;
}
private:
int _a2;
int _a1;
};
int main()
{
A a1;
a1.print();
return 0;
}
这样的代码得出的结果会是什么呢?会是1,1吗?其实当然不会,这个程序得出来的结果其实是:随机值,1。
为神马会这样呢?其实这就跟初始化列表走初始化的顺序有关。想要让两个值都初始化为1。调用一下声明的顺序即可:
class A
{
public:
A()
:_a1(1)
,_a2(_a1)
{
}
void print()
{
cout << "_a1:"<<_a1 << endl;
cout << "_a2:"<<_a2 << endl;
}
private:
int _a1;//调用顺序
int _a2;
};
int main()
{
A a1;
a1.print();
return 0;
}
结果:
3.若声明时给了缺省值,当初始化列表不显示传值的话初始化列表传入的值就是缺省值。若显式调用则为显式调用传入的值。如以下代码:
class A
{
public:
A()
:_a1(1)//显式调用
{
}
void print()
{
cout << "_a1:"<<_a1 << endl;
cout << "_a2:"<<_a2 << endl;
}
private:
int _a1=0;//给上缺省值
int _a2=0;
};
int main()
{
A a1;
a1.print();
return 0;
}
结果:
3.必须要使用初始化列表的场景
1.const成员声明以后要定义赋值时。
2.引用成员要定义赋值时。
3.没有默认构造函数的类对象初始化时。
二,单参数构造函数的隐式类型转换
1.内置类型的隐式类型转换
在自定义类型中会发生隐式类型转换。转换的方式便是生成一个临时的对象,然后这个对象拷贝值再赋值给要初始化的对象。比如:
int main()
{
double a = 1;//给double对象赋一个整型值
int c = 1.00;//给一个int对象赋一个浮点数
cout << "a:"<<a << endl;
cout << "c:" << c << endl;
return 0;
}
这个程序的结果会是什么呢?结果:
如何证明这里发生了隐式类型转换生成了临时对象呢?这里就得用到临时对象的一个特点了:临时对象具有常性。 所以当我们用非const引用对象来接收值时若为临时对象就一定会报错。如下列代码:
int main()
{
double& a = 1;
int& c = 1.00;
cout << "a:"<<a << endl;
cout << "c:" << c << endl;
return 0;
}
结果:
当我们加上const时程序便是正常运行的:
2. 自定义类型的隐式类型转换
既然内置类型有隐式类型转换,那自定义类型也得有隐式类型转换。不过,自定义类型要想有隐式类型转换那就得有一个带参的构造函数。如以下代码:
class B
{
public:
B(int a )
{
_a1 = a;
};
void print()
{
cout << _a1 << endl;
}
private:
int _a1;
};
int main()
{
B a = 1;//正常来说应该是B a(1)这样调用的。
a.print();
return 0;
}
结果:
正常打印
为什么这样也行呢?其实这里便是发生了一个隐式类型转换。在上面代码中,1先调用构造函数把自己转化成了成一个临时的B类型的对象,再将1这个值传入到临时对象中。然后B a通过赋值调用默认生成的拷贝构造函数将临时对象里的值拷贝到a对象中。
3.多参数构造函数的隐式类型转换
多参数构造函数的隐式类型转换是在C++11之后才开始支持的新语法。原理与单参数的构造函数的隐式类型转换一样。但是使用方法不同。使用方法:
class B
{
public:
B(int a ,int b,int c)
{
_a1 = a;
_b1 = b;
_c1= c;
cout << "B(int)" << endl;
};
B(B& B1)
{
cout << "B(int&)" << endl;
}
void print()
{
cout << _a1 << endl;
cout << _b1 << endl;
cout << _c1 << endl;
}
private:
int _a1;
int _b1;
int _c1;
};
int main()
{
B a = { 1,2,3 };//用花括号
a.print();
return 0;
}
结果:
4.当你不想要发生隐式类型转换时便可以使用explicit关键字。