练习14.50
在初始化ex1和ex2的过程中,可能用到哪些类类型的转换序列呢?说明初始化是否正确并解释原因。
struct LongDouble{
LongDouble(double = 0.0);
operator double();
operator float();
};
LongDouble ldObj;
int ex1 = ldObj;
float ex2 = ldObj;
解答:
(1) 类型对象创建是没有问题的。
(2) 在int ex1 = ldObj;这句就会出现问题。
这里会有两个备选转换序列:
double -> int
float -> int
从而造成了二义性,在编译的时候编译器会报错。
(3) float ex2 = lobObj;这个就没有问题。
因为这里的转化序列只有一个:
double -> float;
练习14.51
再调用calc的过程中,可能用到哪些类型转换序列呢?说明最佳可行函数是如何被选出来的。
void calc(int);
void calc(LongDouble);
double dval;
calc(dval); // 哪个clac
解答:
这里用到的转换序列就是double -> int
因为LongDouble是个自定义类型,所以编译器会选择内置类型进行优先转换。
但当我们去掉calc(int)函数,calc(LongDouble)同样会执行,这个时候会有隐式转换,LongDouble -> double,函数将会接受double类型的参数。
练习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; 有以下两个候选函数,从下面两个候选函数就可以看出有哪种类型转换了
operator+(int, double)<built-in>
operator+(int, float)<built-in>
SmallInt -> int, LongDouble->double 或 LongDouble -> float
ld = ld+ si; 有以下两个候选函数,从下面两个候选函数就可以看出有哪种类型转换了
operator+(double, int)<built-in>
operator+(float, int) <built-in>
类型转换序列和上面的一样。
练习14.53
架设我们已经定义了如第522页所示的SmallInt,判断下面的加法表达式是否合法。如果合法,使用了那个加法运算符?如果不合法,应该怎样修改代码才能使其合法?
SmallInt s1;
double d = s1 + 3.14;
解答:
不合法,还是有二义性,以下两个操作为候选操作
operator+(int, double) <built-in>
SmallInt operator+(const SmallInt&, const SmallInt&)
double d = static_cast<double>(s1) + 3.14;
对s1进行强制类型转换,就可以让这段代码合法执行。