C++剖析— 转换构造函数
参考自 狄泰 C++深度解析
我们知道在标准的数据类型之间是有隐式转换的,转换关系如下:
这是 C语言和 C++ 里的转换关系,我们这里主要谈论C++,总所周知C++相比C语言有了一个 类 的概念,类中有构造函数,而当构造函数具有以下特点时会成为转换构造函数:
- 有且只有一个参数
- 参数是基本数据类型
- 参数不是自身类的类型
我们知道,类也是一个数据类型,那么问题来了类和标志数据类型可否相互转换?
先看下面代码:
class Test
{
};
int main()
{
Test t;
t = 5;
reutrn 0;
}
上面的代码编译实际上是会报错的
那么稍作修改看看
class Test
{
public:
Test(int a){}
};
int main()
{
Test t;
t = 5;
reutrn 0;
}
很有趣,竟然通过了, 这是为什么呢?
实际上,这是编译器的行为,编译器会尽量的让代码通过,会进行隐转换,怎么转换?首先编译器看到5这个整型数那么很明显是不能直接赋值到 t 变量的,所以编译器会寻找转换构造函数, 编译器发现在Test 类中正好存在转换构造函数Test(int a), 于是将 t = 5 转换为 t = Test(5) 所以编译就会通过
OK, 我们再看看下面的修改:
class Test
{
public:
int val;
Test(int a){ val = a;}
Test operator + (Test& e)
{
Test ret(val + e.val);
return ret;
}
};
int main()
{
Test t;
t = 5;
Test r;
r = t + 5;
cout<< r.val<< endl;
reutrn 0;
}
上面代码编译结果是什么?
10
这是为什么可以编译通过,有输出?
原理其实和上面红字所说一样, 在编译到 r = t + 5 时候, 编译器发现 5 是整型, 不能直接运算, 所以就找转换构造函数Test(int a),所以 r = t + 5 等价于 r = t + Test(5) 所以可以顺利编译并且有输出了
好了 说完了转换构造函数 那么问题来了: r = t + 5 t = 5; 这些语句实际上使我们想写的吗 ,在我看来,这些语句在工程开发中是手误,不应该存在的,为什么,这是因为,这些语句是不会被编译器认为是错误,程序在执行这些语句会得到我们意想不到的结果,是工程开发中很难发现的bug,我们在开发中实际上本意不是写下这样的代码, 但是编译没有报错,我们就很容易忽略了。
那么怎么解决? C++提供了解决办法,那就是在转换构造函数中声明 explicit 关键字。explicit 关键字 就是杜绝编译器进行隐式转换,只能显示转换
待续。。。