隐式类型转换
之前我们讲过,不同类型的内置类型变量在相互赋值时会有隐式类型转换。
double a = 10.5;
int b = a;
就如上面这个简单的赋值,在a赋值给b之前,会产生一个临时变量,最终赋给b值的就是这个临时变量。
当将不同类型的变量取引用时,需要加const的原因,是因为临时变量具有常性。
double a = 10.5;
// int& b = a;// 报错
// int& c = 10;// 报错
const int& b = a;// 正常运行
const int& c = 10;// 正常运行
上述代码中b取的就是a产生的临时变量的引用,临时变量存储在内存的静态区,具有常性,就跟第四行代码的数字10性质是一样的,当你加上const时,这种引用权限就被放开了,因为const确保了你不会对静态区的变量做出改动。对于C++的自定义类型,与内置类型遵循的规则是一样的。
C++支持一种类型转换式的构造:
class A
{
public:
A(int a)
:_a1(a)
{}
A(const A& aa)
:_a1(aa._a1)
{
cout << "A(const A& aa)" << endl;
}
private:
int _a1;
int _a2;
};
int main()
{
A aa1(1);
A aa2 = 1;
return 0;
}
对于main函数第一行代码是标准的调用了构造函数。而第二行,作为内置类型的1,竟然能给对象的初始化赋值,这是因为在赋值之前,产生了隐式类型转换,1作为一个参数传递给了构造函数,从而产生了一个临时对象,最终临时变量拷贝构造给aa2。
在调用此代码的过程中,我们发现,并没有调用拷贝构造函数,这是因为通过编译器的优化,省去了拷贝构造这一过程,简单来说就是:
这时候看这两行能否运行的原因应该就不困难了:
// A& ref = 10;// 报错
const A& ref = 10;//可运行
// 这里ref引用的是类型转换中用10构造的临时对象
在上面代码中,我们使用的构造函数一直是单参数的,可以使用特殊的隐式类型转换构造。但是如果构造函数是多参数的,该怎么使用类似于A aa = 1;的方式创建对象呢?其实C++提供了解决方案,那就是多参数构造。
class A
{
public:
A(int a1, int a2)
:_a1(a1)
, _a2(a2)
{}
A(const A& aa)
:_a1(aa._a1)
,_a2(aa._a2)
{}
void print()const
{
cout << _a1 << " " << _a2 << endl;
}
private:
int _a1;
int _a2;
};
// 多参数构造
int main()
{
A aa1 = { 2,2 };
aa1.print();
// A& ref = { 2,3 };//报错
const A& ref = { 2,3 };
ref.print();
return 0;
}
explicit关键字
这个知识点稍稍提一下,如果不想允许构造时出现类的隐式类型转换,可以在拷贝构造前加个explicit关键字,就可以成功限制类的隐式类型转换了。
关于explicit的更多使用,在后面有机会还会讲。
成员变量缺省值
之前讲过,在C++11的新标准中,支持为类中的成员变量提供缺省值。在类和对象中,提供的缺省值是提供给初始化列表使用的。由于支持隐式类型转换构造等原因,提供的缺省值可以非常灵活,见代码:
class A
{
public:
A(int a1)
:_a1(a1)
{
cout << "A(int a1)" << endl;
}
A(int a1, int a2)
:_a1(a1)
, _a2(a2)
{
cout << "A(int a1, int a2)" << endl;
}
A(const A& aa)
:_a1(aa._a1)
, _a2(aa._a2)
{
cout << "A(const A& aa)" << endl;
}
private:
int _a1;
int _a2;
};
class B
{
public:
private:
int _b1 = 1;// 缺省值可以给整型变量
int ptr = (int)malloc(40);// 可以开空间给指针
A _aa1 = 1;// 可以给对象类型(A _aa1(1);这样构造是错误的)
A _aa2 = { 1,2 };// 多参数构造
A _aa3 = _aa2;// 拷贝构造,缺省参数甚至可以是一个对象
};
int main()
{
B bb1;
return 0;
}
这些缺省参数,最终都会提供给初始化列表。
结语
本篇博客将最后两个默认成员函数做了一个收尾,再次谈到了构造函数的一些语法和特性,关于初始化列表的概念和使用;一种很新的创建对象方式,隐式类型转换方式创建对象,而explicit关键字可以限制这种转换的发生;最后还提到了C++11的新特性成员变量的缺省值,列出了对象,指针等类型给缺省值的方式。在类和对象的下一篇,会再介绍几个类和对象的小特性,以及编译器做出的优化。
博主还会继续产出有趣的内容,感谢大家的支持!♥