class Sales_data{
public:
Sales_data(string s, unsigned cnt, double price) :
bookNo(s), units_sold(cnt), revenue(cnt*price){}
Sales_data() :Sales_data("", 0, 0){}
Sales_data(string s) :Sales_data(s, 0, 0){}
Sales_data(istream& is) :Sales_data()
{
read(is, *this);
}
string isbn() const { return bookNo; }
Sales_data& combine(const Sales_data&);
double avg_price()const;
//
Sales_data add(const Sales_data&, const Sales_data&);
ostream &print(ostream&, const Sales_data&);
istream &read(istream&, Sales_data&);
private:
string bookNo;
unsigned units_sold;
double revenue;
};
接受string和istream的两个构造函数,分别定义了Sales_data的两种隐式转换的规则
string null_book="9-999-9999-9"
item.combine(null_book);
Sales_data& combine(const Sales_data&);
我们注意到combine原本的参数类型为const Sales_data&
执行item.combine(null_book); 时编译器会自动创建一个Sales_data的对象,新生成的对象被传递给combine
隐式转换只允许一步类型转换
item.combine(“9-9999-99-9”) ; // 错误
这要求先将”9-9999-99-9”隐式转换为string,然后再隐式转换为Sale_data,两步隐式转换是无法实现的
explicit抑制隐式转换
> explicit Sales_data(string s) :Sales_data(s, 0, 0){}
//这时在调用item.combine(null_book);就是错误的,因为无法执行string向Sales_data的隐式转换
explicit 修饰的构造函数只能直接初始化,也就是说
Sales_data item1(null_book);// 正确
Sales_data item2 = null_book; // 错误
直接初始化和拷贝初始化
string s5="hiya"; // 拷贝初始化
string s6("hiya"); // 直接初始化
string s7(10,'c); // 直接初始化
string s8 = string(11,'b');// 拷贝初始化
貌似使用=就是拷贝初始化
当我们使用直接初始化时,编译器使用普通的函数匹配来选择与我们提供的参数最匹配的构造函数。
拷贝初始化: 编译器将右值运算对象拷贝到正在创建的对象中,需要的话,进行类型转换。
拷贝初始化一定要设计到对象的创建,创建对象后再从对象中拷贝成员变量。