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;
}

posted @ 2021-08-18 22:51  Keep_Silent  阅读(8)  评论(0编辑  收藏  举报