1.隐式类型转换
首先什么时候会出现隐式类型转换:
如果构造函数只接受一个实参,则它实际上定义了转换为此类类型的隐式转换机制。我们把这种函数称作转换构造函数。转换构造函数会自动生成一临时对象,然后传递给成员函数(供其使用)。
下面给出了一些代码
string null_book="9-999-99999";
item.combine(null_book);
class Screen{
sales_data& combine(const sales_data&rhs) {
units_sold += rhs.units_sold;
revenue += rhs.revenue;
return *this;
};
#首先我们定义了string对象null_book,之后再combine函数中使用null_book。
成员函数 combine()中只有一个const sales_data& 类型的参数,即combine()可以隐式转换。在接受了一个string 对象 null_book 后,因为只有一个参数所以认为这是一个对象的数据成员。但是实际上并没有null_book这个对象,所以编译器就会创建一个临时对象,然后用构造函数初始化其他数据成员。
此步发生了一个隐式的类型转换,建立了一个临时对象,再调用初始函数完成所有数据成员初始化。
//此步非法,在C++中“字符串”是以C风格字符串,即以数组的形式进行保存的
//类型转换 1.C风格字符串->string 2.string->转换成一个临时对象
//两次类型转换是不被允许的
item.combine("9-999-99999");
//正确,只有一部转换
item.combine(string("9-999-99999"));
但类型转换不总是有效,因为很多时候我们需要长期使用这个对象。
item.combine(cin);
这里隐式地把cin转换成Sales_data,然后接受了一个istream的 Sales_data的构造函数。该构造函数通过读取标准输入创建一个临时对象,并传递给combine
但是此对象为临时量,一旦combine()完成就不能继续访问此对象
简单来说,即我们先利用转换构造函数在类中创建一个临时对象,再把它丢弃。需要规避掉这种情况,所以我们可以引入explicit限定词。
2.explicit 的使用
explicit可以对构造函数加以封锁,使其不能隐式创建对象(即临时对象)。这样函数在调用的时候,只能访问已经创建出来的对象。
通过在函数前加上关键字explicit来完成。
class Sales_data{
public:
Sales_data(const string& s,unsigned n,double p):bookNo(s),units_sold(n),revenue(p*n){};
explicit Sales_data(const string& s):booNo(s){};
explicit Sales_data(iotream&);
此时,我们在如果再操作如下代码是不被允许的
//combine()被 explicit限定不允许创建临时对象,无法通过编译。
item.combine(null_book);
因为只有单个参数的函数会有隐式类型转换(多实参的构造函数不能用于隐式转换),那么explicit只在限制单参数的隐式类型转换中使用。