由于编译器会尽可能的为所有的警告和错误做出解释,但也因此导致了部分情况下的过度解析。
书中给的例子是编译器过度解析,使用了类型转换函数却隐藏了真正的错误。
cin << intval;
int temp = cin.operator int();
temp << intval;
分析一下:
程序员的目的是实现读取输入,但是将 >> 写成了 <<, istream并没有重载 << 运算符,结果编译器按照 << 左移位来解析
要想实现左移位,又必须将cin转成整型。那么编译器会找istream有没有类型转换函数好将cin转成整型后再进行移位操作
如果找到了,那么,cin << intval; 正常执行了。并不报错。
所以为了避免这种转换发生,istream中使用了operator void*()来替换operator int()
隐式类型转换虽然会"暗地里"做一些转换操作,但这种机制的好处也是显而易见的。并且为了解决这个"暗地里"的隐式操作,提供了一个修饰符,即explicit,类型转换构造函数和类型转换函数声明前加上explicit关键字将阻止编译器隐式类型转换操作。任何尝试隐式转换的操作都会报错。
如下:
#include<iostream>
using namespace std;
class A
{
public:
//explicit
A(int a):m_a(a)
{
cout << "construct A from int" << endl;
}
//explicit
operator int()
{
cout <<"convert A to int " << end;
return m_a;
}
public:
int m_a;
};
int main(void)
{
A a(5);//显式类型转换构造
A b = 5;//隐式类型转换构造
int i = a;//隐式类型转换函数
return 0;
}
A a(5);总是正常的。
第一个explicit注释掉,A a(5);运行正常;去掉该注释,编译提示:类型转换失败
第二个explicit注释掉,int i = a;运行正常。 去掉该注释 编译提示:非法的存储类,即赋值失败。
原文地址:https://www.cnblogs.com/kuikuitage/p/9634788.html
时间: 2024-10-29 13:33:35