7.47:说明一个string参数的Sales_data构造函数是否应该是explicit的,并解释这样做的优缺点。
Ans:应该。因为在Sales_data这个类中,当我们输入一个ISBN号,一般还要用户输入一个书的价格和数目,如果不使用explicit声明这个函数时,那么意味着可以进行隐式地转换,但是一旦使用了隐式转换,那么除了这个string参数的值初始化为输入的值外,其他的类的数据成员被默认初始化。与我们的初衷相违背。
优点:防止因为编译器隐式地进行类型转换出现意想不到的错误。
缺点:当我们需要用这种类型转换时,需要显式地使用强制转换来实现,略显繁琐
7.48:假定Sales_data的构造函数不是explict的,则下述定义将执行什么样的操作?
string null_isbn( "9-999-99999-9" );
Sales_data item1(null_isbn);
Sales_data item1("9-999-99999-9");
如果Sales_data的构造函数是explicit的,又会发生什么?
Ans:
若不是explict的:
string null_isbn( "9-999-99999-9" ); //定义一个string类型的对象null_isbn;
Sales_data item1(null_isbn); //会创建一个临时Sales_data对象,可以用来进行隐式地类型转换
Sales_data item1("9-999-99999-9");//直接调用一个构造函数,const char* 转换成string类型。
若是explict的:
string null_isbn( "9-999-99999-9" ); //定义一个string类型的对象null_isbn;
Sales_data item1(null_isbn); //调用构造函数,并用null_isbn初始化,不会创建一个临时对象,也不能进行隐式转换
Sales_data item1("9-999-99999-9");//直接调用一个构造函数,const char* 转换成string类型。
总结:不管是否是explicit,上述的语句均能正常运行。
7.49:对于combine函数的三种不同的声明,当我们调用i.combine(s)时分别发生什么情况?其中i是一个Sales_data,而s是一个string对象。
(a)Sales_data &combine(Sales_data);
(b)Sales_data &combine(Sales_data&);
(a)Sales_data &combine(const Sales_data&) const;
Ans:a)能通过编译。string对象s会使得编译器创建一个临时的Sales_data对象,所以能通过编译。
b)不能通过编译。因为string对象s需要通过常量引用来接收,又因为编译器自动生成了临时的Sales_data对象,但是这个对象需要使用const&来接收,所以编译无法通过。
c)不能通过编译。因为该函数是常成员函数,无法修改对象的值,只能读不能写。
7.51:vector将其单参数的构造函数定义成explicit的,而string则不是,你觉得原因何在?
Ans:string的构造函数的参数类型是const char *,可以看做是string类型,所以无需声明成explicit的;而vector的构造函数的参数是int类型的,用来指定容器的容量的,两者类型语义相差较大,所以使用explicit声明。