在类型较为相近的两个变量中,可以发生隐式类型转换,比如在int和double之间的比较或赋值就能看到有隐式类型转换发生,来看这一段代码:
void Test1()
{
int a = 1;
double d = 2.1;
int res=a > d;
int c = d;
}
不难看出,由于类型不同,a,d在进行比较的时候,必定产生了隐式类型转换,当类型一致时,方可完成比较。
可是,a和d在比较时发生的隐式类型转换,会不会影响a,d本身?
并不会。a和d在进行隐式类型转换时比较,拿的是中间临时变量来比较。
同样,d赋值给c就会先生成一个int类型的临时变量,然后赋值给c。
如果我想通过这个c来看看这个临时变量的属性,即将c变为&,还能不能进行赋值
void Test2()
{
int a = 1;
double d = 2.1;
int res=a > d;
int &c = d;
}
编译报错了。这又为什么,为什么提示说int&类型非常量限定,难道把c变量变成常量属性,即在前面用const修饰,就能编译通过吗
void Test2()
{
int a = 1;
double d = 2.1;
int res=a > d;
const int &c = d;
}
果然,这时候编译器的确没再报错。为什么加上const就能编译通过了?
其实归根结底就是因为临时变量具有常属性 d发生隐式类型转换后中间产生了一个临时变量,这个变量具有常属性,而这个常属性的变量试图赋给一个随时想改变的变量,那不就很扯淡了。再者,根据权限的角度也能说明这个问题,权限不能放大,很明显,这里就是一个权限放大。
以上说的都是内置类型,那自定义类型呢,也会不会有隐式类型转换
在这之前先得创建一个类
class A
{
public:
A(int a)
:_a(a)
{}
private:
int _a;
};
void Test3()
{
A a1 = 1;
A a2 = 1.1;
}
编译通过了,并且经过调试可以看到a1确实是变成了1,所以自定义类型也是存在隐式类型转换的
但也并非任何自定义类型都可以进行隐式类型转换,这里只给了一个参数,那如果是多参数呢
class B
{
public:
B(int b1,int b2)
:_b1(b1)
, _b2(b2)
{}
private:
int _b1;
int _b2;
};
void Test4()
{
B b1(1);
B b2 = 1;
}
显然,这种写法是错误的,参数数量都对不上怎么可能会是正确的代码。但如果b2这样赋值却是可以的:
B b2 = { 1, 2 };
这是C++在这里的规定,不做过多解释。
内置类型对象 隐式转换成自定义类型对象时一定要注意,能支持这个转换,是有A的int单参数构造函数(支持传一个参数多参数带缺省也可以)支持。
有时候我们可能并不希望隐式类型能够随意转换,由此C++引入了一个关键字:exiplicit
explicit关键字 构造函数不仅可以构造与初始化对象,对于单个参数或者除第一个参数无默认值其余均有默认值 的构造函数,还具有类型转换的作用。
class A
{
public:
explicit A(int a)
:_a(a)
{}
private:
int _a;
};
void Test5()
{
A a1 = 1.1;
A a2 = 1;
}
加上explicit关键字后,就限制了隐式类型转换,但也只是限制隐式类型转换。
所以这里想说的是,explicit仍然无法强制类型转换
另外补充一点,用explicit修饰构造函数,将会禁止构造函数的隐式转换。