C++对象模型-构造函数语意学

由于编译器会尽可能的为所有的警告和错误做出解释,但也因此导致了部分情况下的过度解析。
书中给的例子是编译器过度解析,使用了类型转换函数却隐藏了真正的错误。

    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;运行正常。 去掉该注释 编译提示:非法的存储类,即赋值失败。

猜你喜欢

转载自www.cnblogs.com/kuikuitage/p/9634788.html
今日推荐