《C++ Primer》第14章 14.9节习题答案

《C++ Primer》第14章 14.9节习题答案,第1张

《C++ Primer》第14章 14.9节习题答案

《C++ Primer》第14章 *** 作重载与类型转换

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 

using namespace std;

class Date
{
    friend ostream& operator <<(ostream &os, const Date &dt);
public:
    Date()
    {

    }

    Date(int y, int m, int d)
    {
        year = y;
        month = m;
        day = d;
    }

    operator bool()
    {
        vector> days_per_month = {
            {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31},
            {31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}
        };
        cout << "operator bool() is call====================" << endl;
        return 1 <= month && month <= 12 && 1 <= day && day <= days_per_month[isLeapYear() ? 1 : 0][month - 1];
    }

    bool isLeapYear()
    {
        return (year % 4 == 0 && year % 100 != 0) || (year % 400 == 0);
    }

private:
    int year, month, day;
};

ostream& operator<<(ostream& os, const Date& d)
{
    const char sep = 't';
    os << "year:" << d.year << sep << "month:" << d.month << sep << "day:" << d.day << endl;
    return os;
}


int main()
{
    Date date(2018, 23, 32);

    if(date)
        cout << "isYear==================";
    else
        cout << date << endl;

    cout << "Hello World!" << endl;
    return 0;
}

运行结果:

 

练习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);即可。

欢迎分享,转载请注明来源:内存溢出

原文地址:https://54852.com/zaji/4751806.html

(0)
打赏 微信扫一扫微信扫一扫 支付宝扫一扫支付宝扫一扫
上一篇 2022-11-08
下一篇2022-11-08

发表评论

登录后才能评论

评论列表(0条)

    保存