一、关键点
类类型转换运算符
二、转换构造函数——隐式的类类型转换
转换构造函数:该构造函数只接受一个实参,它实际定义了从构造函数的参数类型向类类型隐式转换的规则
重点是:如何使用该条规则
class Sales_data {
public:
Sales_data() = default;
Sales_data(const string &s): bookNo(s) {}
Sales_data(const Sales_data &item) = default;
Sales_data& operator=(const Sales_data &item) {
bookNo = item.bookNo;
units_sold = item.units_sold;
revenue = item.revenue;
return *this;
}
private:
string bookNo;
unsigned units_sold = 0;
double revenue = 0.0;
};
int main()
{
string isbn = "league";
Sales_data book1(isbn); //直接初始化
Sales_data book2 = isbn; //拷贝初始化
Sales_data book3;
book3 = isbn; //string类型隐式转换为Sales_data类型
return 0;
}
上面“book3 = isbn;”语句包含string类型向Sales_data类型的隐式转换,因为Sales_data有转换构造函数(而该函数中的参数类型为string)。
我们要想该隐式转换(即“book3 = isbn;”)失效,可以将转换构造函数指定为explicit 的,这样不仅该转换失效,拷贝初始化也将失效。
三、类型转换运算符
类型转换运算符:成员函数,负责将该类类型转换为其他类型
重点是:如何定义和运用、由此带来的缺漏
class A {
public:
A(int i = 0): val(i) {} //转换构造函数
operator int() const { return val; }
private:
size_t val;
};
int main()
{
A a;
a = 2; //int类型向A类型的隐式转换(转换构造函数使然)
int sum = a + 3; //A类型向int类型的转换 (类型转换运算符使然)
auto ans = a + 3.14; //A类型先转换为int类型,然后内置类型转换将所得的int继续转换成double
return 0;
}
【缺点】
如果每个类都定义了向bool的类型转换运算符,那么语句“int i = 2; cin << i;”将是合法的,istream类型的bool类型转换运算符将cin转换成bool,而这个bool值接着会被提升成int并用作内置的左移运算符的左侧运算对象。(为了避免此情况,引入了显式的类型转换运算符<类型转换运算符定义为explicit的>,编译器不会自动执行这一类型转换,但是有例外:表达式被用作条件,编译器会将显式的类型转换自动应用于它)
避免二义性转换:定义两种将同一类型转换成同另一类型的方法、类中定义了多个与算术类型相关的转换