C++ 隐式的类类型转换 explicit学习
C++ primer 5e中练习7.48中
假定Sales_data的构造函数不是explicit的,则下述定义将执行什么样的操作?
string null_isbn("999");
Sales_data item1(null_isbn);
Sales_data item2("999999");
如果Sales_data的构造函数时explicit的,又会发生什么呢?
https://github.com/pezy/CppPrimer/tree/master/ch07#exercise-748
这个答案没有任何问题,在评论区有人问:” 48题的item2,这个不是从字面值转为string,然后再转为Sales_data吗?执行了两次类型转换,为什么不报错??书上不是说了,编译器只会自动执行一步类型转换吗“
是不是执行了两次类型转换?
明显,这里并没有执行两次类型转换,而是一次类型转换+一次构造函数调用
/*情况 1 */
//相当于调用了参数为string的构造函数
string null_book = "999";
Sales_data item1(null_book);
//将字符串字面值转为string后再调用对应的构造函数
Sales_data item2("999");
//------------------------------------------------------------------
/*情况 2 无explicit */
Sales_data item3;
//错误,需要转换两次--字符串字面值转string,string隐式调用(转换)Sales_data
item3.combine("999");
//正确,隐式调用构造函数,然后传入combine
item3.combine(string("999"));
//正确,将字符串字面值转换为string后调用对应的构造函数再传入combine
item3.combine(Sales_data("999"));
//------------------------------------------------------------------
/*情况 3 有explicit */
Sales_data item4;
//错误,同item3.combine("999");
item4.combine("999");
//错误,无法隐式调用构造函数
item4.combine(string("999"));
//正确,字符串字面值转为string后调用构造函数再传入combine
item4.combine(Sales_data("999"));
附完整代码进行测试:
#include <iostream>
#include <string>
//为方便测试,将类定义整合进一个cpp文件中
struct Sales_data {
//Sales_data() = default;
//构造函数1
Sales_data(const std::string& s, unsigned n, double p)
: bookNo(s), units_sold(n), revenue(n * p){ std::cout<<"1,2,3"<<std::endl; }
//构造函数2
Sales_data(const std::string &s):Sales_data(s,0,0) { std::cout<<"1"<<std::endl;}
//explicit Sales_data(const std::string &s)::Sales_data(s,0,0) { std::cout<<"1"<<std::endl; }
//构造函数3
std::istream& read(std::istream &,Sales_data&); //read的声明位置并无影响
Sales_data(std::istream &is):Sales_data() { std::cout<<"istream"<<std::endl; read(is, *this); }
//构造函数4
Sales_data():Sales_data("",0,0) { std::cout<<"()"<<std::endl;; };
std::string isbn() const { return bookNo; };
Sales_data& combine(const Sales_data&);
std::string bookNo = "";
unsigned units_sold = 0;
double revenue = 0.0;
};
// nonmember functions
std::istream& Sales_data::read(std::istream& is, Sales_data& item)
{
double price = 0;
is >> item.bookNo >> item.units_sold >> price;
item.revenue = price * item.units_sold;
return is;
}
std::ostream& print(std::ostream& os, const Sales_data& item)
{
os << item.isbn() << " " << item.units_sold << " " << item.revenue;
return os;
}
Sales_data add(const Sales_data& lhs, const Sales_data& rhs)
{
Sales_data sum = lhs;
sum.combine(rhs);
return sum;
}
Sales_data& Sales_data::combine(const Sales_data& rhs)
{
units_sold += rhs.units_sold;
revenue += rhs.revenue;
return *this;
}
int main()
{
//情况 1
std::string null_book = "999";
Sales_data item1(null_book); //相当于调用了参数为string的构造函数
Sales_data item2("999"); //将字符串字面值转为string后再调用对应的构造函数
//情况 2 无explicit
Sales_data item3;
item3.combine("999"); //错误,需要转换两次
item3.combine(std::string("999")); //正确,隐式调用构造函数,然后传入combine
item3.combine(Sales_data("999")); //正确,将字符串字面值转换为string后调用对应的构造函数再传入combine
//情况 3 有explicit
Sales_data item4;
item4.combine("999"); //错误,同item3.combine("999");
item4.combine(std::string("999")); //错误,无法隐式调用构造函数
item4.combine(Sales_data("999")); //正确,字符串字面值转为string后调用构造函数再传入combine
return 0;
}