
14.9节 重载、类型转换与运算符 习题答案
练习14.45:编写类型转换运算符将一个Sales_data对象分别转换成string和double,你认为这些运算符的返回值应该是什么?
【出题思路】
理解类型转换运算符。
【解答】
如果要转换成string,那么返回值应该是bookNo。
如果要转换成double,那么返回值应该是revenue。
练习14.46:你认为应该为Sales_data类定义上面两种类型转换运算符吗?应该把它们声明成explicit的吗?为什么?
【出题思路】
理解类型转换运算符。
【解答】
Sales_data类不应该定义这两种类型转换运算符,因为对于该类来讲,它包含三个数据成员:bookNo、units_sold和revenue,只有三者在一起才是有效的数据。但是如果确实想要定义这两个类型转换运算符的话,应该把它们声明成explicit的,这样可以防止Sales_data在某些情况下被默认转换成string或double类型,这有可能导致我们意料之外的运算结果。
练习14.47:说明下面这两个类型转换运算符的区别。
struct Integral{
operator const int();
operator int() const;
}
【出题思路】
理解类型转换运算符。
【解答】
前者将对象转换成const int,在接受const int值的地方才能够使用。后者则将对象转换成int值,相对来说更加通用一些。
练习14.48:你在7.5.1节的练习7.40(第261页)中曾经选择并编写了一个类,你认为它应该含有向bool的类型转换运算符吗?如果是,解释原因并说明该运算符是否应该是explicit的;如果不是,也请解释原因。
【出题思路】
理解类型转换运算符。
【解答】
在练习7.40中,我们编写了类Date,它含有3个数据成员:year、month和day。我们可以为Date类提供一个bool类型的转换运算符,用来检查3个数据成员是否都是有效值(比如month是否介于1~12之间,day是否超出了当月的天数)。bool类型转换运算符应该声明为explicit的,因为我们是有意要在条件表达式中使用它的。
练习14.49:为上一题提到的类定义一个转换目标是bool的类型转换运算符,先不用在意这么做是否应该。
【出题思路】
本题练习类型转换运算符。
【解答】
#include#include #include #include #include #include
运行结果:
练习14.50:在初始化ex1和ex2的过程中,可能用到哪些类类型的转换序列呢?说明初始化是否正确并解释原因。
struct LongDouble {
LongDouble(double = 0.0);
operator double();
operator float();
};
LongDouble ldObj;
int ex1 = ldObj;
float ex2 = ldObj;
【出题思路】
理解类型转换运算符。
【解答】
对于int ex1 = ldObj;,它需要把LongDouble类型转换成int类型,但是LongDouble并没有定义对应的类型转换运算符,因此它会尝试使用其他的来进行转换,其中operator double()和operator float()都满足需求。但编译器无法确定哪一个更合适,因此会产生二义性错误:conversion from 'LongDouble' to 'int'is ambiguous。对于float ex2 = ldObj;,它需要把LongDouble转换成float类型,而我们恰好定义了对应的类型转换运算符,因此只需要直接调用operator float()即可。
练习14.51:在调用calc的过程中,可能用到哪些类型转换序列呢?说明最佳可行函数是如何被选出来的。
void calc(int0; void calc(LongDouble); double dval; calc(dval); //哪个calc?
【出题思路】
理解类型转换运算符。
【解答】
这里会优先调用void calc(int)函数。因为double转换为int是标准类型转换,而转换为LongDouble则是转换为用户自定义类型,实际上是调用了转换构造函数,因此前者优先。
练习14.52:在下面的加法表达式中分别选用了哪个operator+?列出候选函数、可行函数及为每个可行函数的实参执行的类型转换:
struct LongDouble {
//用于演示的成员operator+;在通常情况下+是个非成员
LongDouble operator+(const SmallInt &);
//其他成员与14.9.2节(第521页)一致
};
LongDouble operator+(LongDouble&, double);
SmallInt si;
LongDouble ld;
ld = si + ld;
ld = ld + si;
【出题思路】
理解类型转换运算符。
【解答】
对于ld=si+ld,由于LongDouble不能转换为SmallInt,因此SmallInt的成员operator+和friend operator+都不可行。
由于SmallInt不能转换为LongDouble,LongDouble的成员operator+和非成员opeartor+也都不可行。由于SmallInt可以转换为int,LongDouble可以转换为float和double,所以内置的opeartor+(int, float)和operator+(int, double)都可行,会产生二义性。对于ld=ld+si,类似上一个加法表达式,由于SmallInt不能转换为double,LongDouble也不能转换为SmallInt,因此SmallInt的成员operator+和两个非成员operator+都不匹配。LongDouble的成员operator+可行,且为精确匹配。
SmallInt可以转换为int,LongDouble可以转换为float和double,因此内置的opeartor+(float, int)和operator+(double, int)都可行。但它们都需要类型转换,因此LongDouble的成员operator+优先匹配。
练习14.53:假设我们已经定义了如第522页所示的SmallInt,判断下面的加法表达式是否合法。如果合法,使用了哪个加法运算符?如果不合法,应该怎样修改代码才能使其合法?
SmallInt s1; double d = s1 + 3.14;
【出题思路】
理解类型转换运算符。
【解答】
如上一题所述,内置的operator+(int, double)是可行的,而3.14可以转换为int,然后再转换为SmallInt,所以SmallInt的成员operator+也是可行的。两者都需要进行类型转换,所以会产生二义性。改为:double d = s1 + SmallInt(3.14);即可。
欢迎分享,转载请注明来源:内存溢出
微信扫一扫
支付宝扫一扫
评论列表(0条)