一、隐式的类类型转换
如果构造函数只接受一个实参,则它实际上定义了转换为此类类型的隐式转换机制,把这种构造函数称作转换构造函数。
class Sales_data{
public:
Sales_data(string s,int cnt,double price);
Sales_data(string s);
Sales_data(istream &is);
private:
string bookNo;
int units_sold;
double revenue;
};
string null_book ="9-999";
//构造一个临时的Sales_data对象
//等价于bookNo等于nullbook
item.combine(null_book);
在Sales_data类中,接受string的构造函数和接受istream的构造函数分别定义了从这两种类型向Sales_data隐式转换的规则。在需要使用Sales_data的地方,可以使用string或者istream作为替代。
二、抑制构造函数定义的隐式转换
C++提供了关键字explicit,禁止通过构造函数进行隐式转换。声明为explicit的构造函数不能在隐式转换中使用。
class Data
{
private:
int num;
public:
explicit Data(int n):num(n){}
void showNum(void)
{
cout<<"num="<<num<<endl;
}
};
int main()
{
//隐式转换
//Data data=10; //explicit该有参构造函数不允许隐式转换
Data data(10);
data.showNum();
Data ob=Data(10); //允许
ob.showNum();
return 0;
}
关键字explicit只对一个实参的构造函数有效。需要多个实参的构造函数不能用于执行隐式转换,所以不需要指定为explicit的。
只能在类内声明构造函数时使用explicit关键字,在类外部定义时不应重复:
//错误:explicit关键字只允许出现在类内的构造函数声明处
explicit Data::Data(int n)
{
//错误
}
explicit构造函数只能用于直接初始化
发生隐式转换的一种情况是当执行拷贝形式的初始化时(使用=),此时,我们只能使用直接初始化而不能使用explicit构造函数:
Data item(null_num); //正确:直接初始化
//错误:不能将explicit构造函数用于拷贝形式的初始化过程
Data item2 = null_num;
为转换显示地使用构造函数
编译器不会将explicit的构造函数用于隐式转换过程,但是可以使用这样的构造函数显示地强制进行转换:
//正确:实参是一个显示构造的Data对象
item.combine(Data(null_num));
//正确:static_cast可使用explicit的构造函数
//使用static_cast执行显式的而非隐式转换
item.combine(static_cast<Data>(cin));
在第一个调用中,可以直接使用Data的构造函数,该调用通过接受string对象的构造函数创建了一个临时的Data对象。
在第二个调用中,使用static_cast使用istream构造函数创建了一个临时的Data对象。