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

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

14.3节  算术和关系运算符  习题答案

练习14.13:你认为Sales_data类还应该支持哪些其他算术运算符(参见表4.1,第124页)?如果有的话,请给出它们的定义。

【出题思路】

本题练习重载运算符的实现。

【解答】

对于Sales_data类,其实我们并不需要再为它添加其他算术运算符。但是这里我们可以考虑为它实现一个减法运算符。

#ifndef SALES_DATA14_13_H
#define SALES_DATA14_13_H


#include <iostream>
#include <string>

class Sales_data
{
    friend std::istream& operator>>(std::istream&, Sales_data&);
    friend std::ostream& operator<<(std::ostream&, const Sales_data&);
    friend bool operator<(const Sales_data&, const Sales_data&);
    friend bool operator==(const Sales_data&, const Sales_data&);
    friend Sales_data operator-(const Sales_data &lhs, const Sales_data &rhs);//重载减法运算符

public:
    Sales_data() = default;
    Sales_data(const std::string &book): bookNo(book) {  }
    Sales_data(std::istream &is) { is >> *this; }

public:
    Sales_data& operator+=(const Sales_data&);
    Sales_data& operator-=(const Sales_data &rhs);//重载-=运算符
    std::string isbn() const { return bookNo; }
    double avg_price() const;

private:
    std::string bookNo;                 //书号
    unsigned units_sold = 0;            //出售册数
    double revenue = 0.0;               //收入
};

inline bool compareIsbn(const Sales_data &lhs, const Sales_data &rhs)
{
    return lhs.isbn() == rhs.isbn();
}

Sales_data operator+(const Sales_data&, const Sales_data&);

inline bool operator==(const Sales_data &lhs, const Sales_data &rhs)
{
    return (lhs.units_sold == rhs.units_sold) &&
           (lhs.revenue == rhs.revenue) &&
           (lhs.isbn() == rhs.isbn());
}

inline bool operator !=(const Sales_data &lhs, const Sales_data &rhs)
{
    return !(lhs == rhs);
}

Sales_data& Sales_data::operator +=(const Sales_data& rhs)
{
    units_sold += rhs.units_sold;
    revenue += rhs.revenue;
    return *this;
}

Sales_data operator +(const Sales_data& lhs, const Sales_data& rhs)
{
    Sales_data ret(lhs);
    ret += rhs;
    return ret;
}
//添加重载-运算符
Sales_data operator-(const Sales_data &lhs, const Sales_data &rhs)
{
    Sales_data sub = lhs;
    sub -= rhs;
    return sub;
}
//添加重载-=运算符
Sales_data& Sales_data::operator-=(const Sales_data &rhs)
{
    units_sold -= rhs.units_sold;
    revenue -= rhs.revenue;
    return *this;
}

std::istream& operator>>(std::istream& in, Sales_data& s)
{
    double price;
    in >> s.bookNo >> s.units_sold >> price;

    if(in)
        s.revenue = s.units_sold * price;
    else
        s = Sales_data();

    return in;
}

std::ostream& operator <<(std::ostream& out, const Sales_data& s)
{
    const char sep = '\t';
    out << "\n\t" << s.isbn() << sep << s.units_sold << sep
        << s.revenue << sep << s.avg_price();

    return out;
}

double Sales_data::avg_price() const
{
    if(units_sold)
        return revenue / units_sold;
    else
        return 0;
}

#endif // SALES_DATA14_13_H
#include "Sales_data14_13.h"

#include <iostream>


using namespace std;

int main()
{
    Sales_data trans1, trans2;
    std::cout << "请输入两条ISBN相同的销售记录:" << std::endl;
    std::cin >> trans1 >> trans2;

    std::cout << "两条销售记录的差" << trans1 - trans2 << std::endl;

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

运行结果:

练习14.14:你觉得为什么调用operator+=来定义operator+比其他方法更有效?

【出题思路】

理解重载运算符的不同实现方式。

【解答】

显然,从头实现operator+的方式与借助operator+=实现的方式相比,在性能上没有优势,而可读性上后者显然更好。因此,在此例中代码复用是最好的方式。

练习14.15:你在7.5.1节的练习7.40(第261页)中曾经选择并编写了一个类,你认为它应该含有其他算术运算符吗?如果是,请实现它们;如果不是,解释原因。

【出题思路】

本题练习实现重载运算符。

【解答】

在练习7.40中,我们编写了类Date。算术运算对Date并没有太大意义,因此不需要为Date重载算术运算符。

练习14.16:为你的StrBlob类(参见12.1.1节,第405页)、StrBlobPtr类(参见12.1.6节,第421页)、StrVec类(参见13.5节,第465页)和String类(参见13.5节,第470页)分别定义相等运算符和不相等运算符。

【出题思路】

本题练习实现相等运算符。

【解答】

//为StrBlob定义==和!=
class StrBlob{
    friend bool operator==(const StrBlob &lhs, const StrBlob &rhs);
    friend bool operator!=(const StrBlob &lhs, const StrBlob &rhs);
    //其他成员
};

bool operator==(const StrBlob &lhs, const StrBlob &rhs)
{
    return lhs.data == rhs.data;
}

bool operator!=(const StrBlob &lhs, const StrBlob &rhs)
{
    return !(lhs == rhs);
}
//为StrBlobPtr定义==和!=
class StrBlobPtr{
    friend bool operator==(const StrBlobPtr &lhs, const StrBlobPtr &rhs);
    friend bool operator!=(const StrBlobPtr &lhs, const StrBlobPtr &rhs);
    //其他成员
};

bool operator==(const StrBlobPtr &lhs, const StrBlobPtr &rhs)
{
    auto l = lhs.wptr.lock();
    auto r = rhs.wptr.lock();
    if(l == r)
        //两个指针都为空,或指向相同vector且curr指向相同元素时,相等,否则不等
        return (!r || lhs.curr == rhs.curr);
    else
        return false;//指向不同vector时,不等
}

bool operator!=(const StrBlobPtr &lhs, const StrBlobPtr &rhs)
{
    return !(lhs == rhs);
}
//为StrVec定义==和!=
class StrVec{
    friend bool operator==(const StrVec &lhs, const StrVec &rhs);
    friend bool operator!=(const StrVec &lhs, const StrVec &rhs);
    //其他成员
};

bool operator==(const StrVec &lhs, const StrVec &rhs)
{
    if(lhs.size() != rhs.size())
        return false;

    for(auto itr1 = lhs.begin(), itr2 = rhs.begin(); itr1 != lhs.end(),
        itr2 != rhs.end(); itr1++, itr2++)
    {
        if(*itr1 != *itr2)
            return false;
    }

    return true;
}

bool operator!=(const StrVec &lhs, const StrVec &rhs)
{
    return !(lhs == rhs);
}
//为String定义==和!=
class String{
    friend bool operator==(const String &lhs, const String &rhs);
    friend bool operator!=(const String &lhs, const String &rhs);
    //其他成员

private:
    const char *str;
};

bool operator==(const String &lhs, const String &rhs)
{
   return strcmp(lhs.str, rhs.str);
}

bool operator!=(const String &lhs, const String &rhs)
{
    return !(lhs == rhs);
}

练习14.17:你在7.5.1节的练习7.40(第261页)中曾经选择并编写了一个类,你认为它应该含有相等运算符吗?如果是,请实现它;如果不是,解释原因。

【出题思路】

本题练习判断类是否需要相等运算符及实现。

【解答】

在练习7.40中,我们实现了Date类。因为我们可以比较两个日期是否相等,因此需要实现相等运算符。

#include <iostream>

using namespace std;

class Date
{
    friend std::istream& operator>>(std::istream&, Date&);
    friend ostream& operator<<(ostream &os, const Date &dt);
    friend bool operator==(const Date &d1, const Date &d2);
    friend bool operator!=(const Date &d1, const Date &d2);

public:
    Date()
    {

    }

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

private:
    int year;
    int month;
    int day;
};

istream& operator>>(std::istream& is, Date& inDt)
{
    is >> inDt.year >> inDt.month >> inDt.day;
    if(!is)
    {
        inDt = Date(0, 0, 0);
        cout << "input data error====================" << endl;
    }
    return is;
}

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;
}

bool operator==(const Date &d1, const Date &d2)
{
    return (d1.year == d2.year) && (d1.month == d2.month) && (d1.day == d2.day);
}

bool operator!=(const Date &d1, const Date &d2)
{
    return !(d1 == d2);
}

int main()
{
    Date date1(2017, 8, 7);
    Date date2(2017, 8, 8);
    bool isEqual = (date1 != date2);
    cout << "date==========" << isEqual << endl;
    return 0;
}

运行结果:date==========1

练习14.18:为你的StrBlob类、StrBlobPtr类、StrVec类和String类定义关系运算符。

【出题思路】

本题练习实现关系运算符。

【解答】

本题的关键是明确关系运算符的语义。

String类的关系运算符就是比较两个字符串字典序的先后。

//为String定义<, <=, >,>=
class String{
    friend bool operator<(const String &s1, const String &s2);
    friend bool operator<=(const String &s1, const String &s2);
    friend bool operator>(const String &s1, const String &s2);
    friend bool operator>=(const String &s1, const String &s2);
    //其他成员

private:
    const char *str;
};

bool operator<(const String &s1, const String &s2)
{
   return strcmp(s1.str, s2.str) < 0;
}

bool operator<=(const String &s1, const String &s2)
{
    return strcmp(s1.str , s2.str) <= 0;
}

bool operator >(const String &s1, const String &s2)
{
    return strcmp(s1.str, s2.str) > 0;
}

bool operator >=(const String &s1, const String &s2)
{
    return strcmp(s1.str, s2.str) >= 0;
}

练习14.19:你在7.5.1节的练习7.40(第261页)中曾经选择并编写了一个类,你认为它应该含有关系运算符吗?如果是,请实现它;如果不是,解释原因。

【出题思路】

本题练习实现关系运算符。

【解答】

在练习7.40中,我们编写了类Date。对于日期,可以比较其大小,因此需要为它重载关系运算符。

#include <iostream>

using namespace std;

class Date
{
    friend std::istream& operator>>(std::istream&, Date&);
    friend ostream& operator<<(ostream &os, const Date &dt);
    friend bool operator==(const Date &d1, const Date &d2);
    friend bool operator!=(const Date &d1, const Date &d2);
    friend bool operator<(const Date &d1, const Date &d2);
    friend bool operator<=(const Date &d1, const Date &d2);
    friend bool operator>(const Date &d1, const Date &d2);
    friend bool operator>=(const Date &d1, const Date &d2);

public:
    Date()
    {

    }

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

private:
    int year;
    int month;
    int day;
};


istream& operator>>(std::istream& is, Date& inDt)
{
    is >> inDt.year >> inDt.month >> inDt.day;
    if(!is)
    {
        inDt = Date(0, 0, 0);
        cout << "input data error====================" << endl;
    }
    return is;
}

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;
}

bool operator==(const Date &d1, const Date &d2)
{
    return (d1.year == d2.year) && (d1.month == d2.month) && (d1.day == d2.day);
}

bool operator!=(const Date &d1, const Date &d2)
{
    return !(d1 == d2);
}

bool operator<(const Date &d1, const Date &d2)
{
    return (d1.year < d2.year) || (d1.year == d2.year && d1.month < d2.month)
            ||(d1.year == d2.year && d1.month == d2.month && d1.day < d2.day);
}

bool operator <=(const Date &d1, const Date &d2)
{
    return (d1 < d2) || (d1 == d2);
}

bool operator >(const Date &d1, const Date &d2)
{
    return !(d1 <= d2);
}

bool operator >=(const Date &d1, const Date &d2)
{
    return (d1 > d2) || (d1 == d2);
}

int main()
{
    Date date1(2017, 8, 7);
    Date date2(2017, 8, 8);
    bool isValue = (date1 >= date2);
    cout << "date==========" << isValue << endl;

    return 0;
}

运行结果:date==========0

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值