隐式的类类型转化

隐式的类类型转换
如果构造函数只接受一个实参,则它实际上定义了转换为此类类型的隐式转换机制,有时我们把这种构造函数称作转换构造函数

能通过一个实参调用的构造函数定义了一条从构造函数的参数类型向类类型隐式转换的规则。

在Sales_data类中,接受string的构造函数和接受istream&的构造函数分别定义了从这两种类型向Sales_data隐式转换的规则。也就是说,在需要使用Sales_data的地方,我们可以使用string或者istream&作为代替:

string null_book="9-999-99999-9";
//构造一个临时的Sales_data对象
//该对象的units_sold和revenue等于0,bookNo等于null_book
item.combine(null_book);

在这里我们用一个string实参调用了Sales_data的combine成员。该调用是合法的,编译器用给定的string自动创建了一个Sales_data对象。新生成的这个(临时)Sales_data对象被传递给combine。因为combine 的参数是一个常量引用,所以我们可以给该参数传递一个临时量。

只允许一步类类型转换

编译器只会自动地执行一步类型转换。例如,因为下面的代码隐式地使用了两种转换规则,所以它是错误的:

//错误:需要用户定义的两种转换:
//(1)把"9-999-99999-9"转换成string
//(2)再把这个(临时的)string转换成Sales_data
item.combine("9-999-99999-9");

如果我们想完成上述调用,可以显式地把字符串转换成string或者Sales_data对象:

//正确:显式地转换成string,隐式地转换成Sales_data
item.combine(string("9-999-99999-9"));
//正确:隐式地转换成string,显式地转换成Sales_data
item.combine(Sales_data("9-999-99999-9"));

类类型转换不总是有效

是否需要从string到Sales_data的转换依赖于我们对用户使用该转换的看法:

//使用istream构造函数创建一个函数传递给combine
item.combine(cin);

这段代码隐式地把cin转换成Sales_data,这个转换执行了接受一个istream的Sales_data构造函数。该构造函数通过读取标准输入创建了一个(临时的)Sales_data对象,随后将得到的对象传递给combine。
Sale_data对象是个临时量,一旦combine完成我们就不能再访问它了。实际上,我们构建了一个对象,先将它的值加到item中,随后将其丢弃。

抑制构造函数定义的隐式转换

在要求隐式转换的程序上下文中,我们可以通过将构造函数声明为explicit加以阻止:

class Sales_data{
public :
Sales_data()=default;
Sales_data(const std::string &s,unsigned n,double p):bookNo(s),units_sold(n),revenue(n*p){}
explicit Sales_data(const std::string &s):bookNo(s){}
explicit Sales_data(std::istream&);
//其他成员与之前的版本一致
};

此时,没有任何构造函数能用于隐式地创建Sales_data对象,之前的两种用法都无法通过编译:

item.combine(null_book); //错误:string构造函数是explicit的
item.combine(cin); //错误:istream构造函数是explicit的

关键字explicit只对一个实参的构造函数有效。需要多个实参的构造函数不能用于执行隐式转换,所以无须将这些构造函数指定为explicit的。只能在类内声明构造函数时使用explicit关键字,在类外部定义时不应重复:

//错误:explicit关键字只允许出现在类内的构造函数声明处
explicit Sales_data::Sales_data(istream& is){
read(is,*this);
}

explicit构造函数只能用于直接初始化
发生隐式转换的一种情况是当我们执行拷贝形式的初始化时(使用=)。此时,我们只能使用直接初始化而不能使用explicit构造函数:

//正确:实参是一个显式构造的Sales_data对象
item.combine(Sales_data(null_book));
//正确:static_cast可以使用explicit的构造函数
item.combine(static_cast<Sales_data>(cin));

在第一个调用中,我们直接使用Sales_data的构造函数,该调用通过接受string的构造函数创建了一个临时的Sales_data对象。在第二个调用中,我们使用static_cast执行了显式的而非隐式的转换。其中,static_cast使用istream构造函数创建了一个临时的Sales_data对象。

标准库中含有显式构造后函数的类

我们用过的一些标准库的类含有单参数的构造函数:
·接受一个单参数的const char*的string构造函数不是explicit的。
·接受一个容量参数的vector构造函数是explicit的。

转载于:https://www.cnblogs.com/CharlesNels/p/9555807.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值