C++ Primer(第五版)|练习题答案与解析(第十四章:重载运算与类型转换)

C++ Primer(第五版)|练习题答案与解析(第十四章:重载运算与类型转换)

本博客主要记录C++ Primer(第五版)中的练习题答案与解析。
参考:C++ Primer
C++ Primer

练习题14.1

在什么情况下重载的运算符与内置运算符有所区别?在什么情况下重载的运算符又与内置运算符一样?

区别:

  • P490,重载运算符必须是一个类的成员或者至少有一个参数是类类型。
  • P491,可以直接通过对象调用一个重载运算符,如data1.operator+(data2)。
  • P491,使用重载的运算符本质上是函数调用,所以这些运算符指定了运算对象的求值顺序或短路求值属性,这些规则无法应用到重载运算符上,比如逻辑运算符、关系运算符和逗号运算符,不建议使用。

相同

  • P490,重载运算符的优先级和结合律与对应的内置运算符保持一致。

练习题14.2

为Sales_data编写重载的输入、输出、加法和复合赋值运算符。

//.h文件
#include <string>
#include <iostream>

class Sales_data {
   
    friend std::istream& operator>>(std::istream&, Sales_data&); // input
    friend std::ostream& operator<<(std::ostream&, const Sales_data&); // output
    friend Sales_data operator+(const Sales_data&, const Sales_data&); // addition

public:
    Sales_data(const std::string &s, unsigned n, double p):bookNo(s), units_sold(n), revenue(n*p){
    }
    Sales_data() : Sales_data("", 0, 0.0f){
    }
    Sales_data(const std::string &s) : Sales_data(s, 0, 0.0f){
    }
    Sales_data(std::istream &is);

    Sales_data& operator+=(const Sales_data&); // compound-assignment
    std::string isbn() const {
    return bookNo; }

private:
    inline double avg_price() const;

    std::string bookNo;
    unsigned units_sold = 0;
    double revenue = 0.0;
};
std::istream& operator>>(std::istream&, Sales_data&);
std::ostream& operator<<(std::ostream&, const Sales_data&);
Sales_data operator+(const Sales_data&, const Sales_data&);
inline double Sales_data::avg_price() const
{
   
    return units_sold ? revenue/units_sold : 0;
}
//.cpp文件
Sales_data::Sales_data(std::istream &is) : Sales_data()
{
   
    is >> *this;
}

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

std::istream& operator>>(std::istream &is, Sales_data &item)
{
   
    double price = 0.0;
    is >> item.bookNo >> item.units_sold >> price;
    if (is)
        item.revenue = price * item.units_sold;
    else
        item = Sales_data();
    return is;
}
std::ostream& operator<<(std::ostream &os, const Sales_data &item)
{
   
    os << item.isbn() << " " << item.units_sold << " " << item.revenue << " " << item.avg_price();
    return os;
}
Sales_data operator+(const Sales_data &lhs, const Sales_data &rhs)
{
   
    Sales_data sum = lhs;
    sum += rhs;
    return sum;
}
//测试文件
int main()
{
   
    Sales_data test;
    std::cin >> test;
    std::cout << test << std::endl;
}

测试:

ISN1913 10 5
ISN1913 10 50 5

练习题14.3

string和vector都定义了重载的==以比较各自的对象,假设svec1和svec2是存放string的vector,确定在下面的表达式中分别使用了哪个版本的==?

(a ) "cobble" == "stone" string重载的“==”
(b ) svec1[0] == svec2[0] string重载的“==”
(c ) svec1 == svec2 vector重载的“==”
(d ) svec1[0] == "stone" string重载的“==”

练习题14.4

如何确定下列运算符是否应该是类的成员?

P493
(a ) % 一般定义为非成员。
(b ) %= 一般定义为类成员,能够改变对象的状态。
(c ) ++ 一般定义为类成员,能够改变对象的状态。
(d ) -> 必须定义为类成员
(e ) << 一般定义为非成员
(f )&& 一般定义为非成员。
(g ) == 一般定义为非成员。
(h ) () 必须定义为类成员

练习题14.5

在7.5.1节练习7.40中,编写了下列类中某一个的框架,请问在这个类中应该定义重载的运算符吗?如果是,请写出来。
(a) Book (b) Date © Employee (d) Vehicle (e) Object (f) Tree

//.h文件
#include <iostream>
#include <string>

class Book {
   
    friend std::istream& operator>>(std::istream&, Book&);
    friend std::ostream& operator<<(std::ostream&, const Book&);
    friend bool operator==(const Book&, const Book&);
    friend bool operator!=(const Book&, const Book&);

public:
    Book() = default;
    Book(unsigned no, std::string name, std::string author, std::string pubdate):no_(no), name_(name), author_(author), pubdate_(pubdate) {
    }
    Book(std::istream &in) {
    in >> *this; }

private:
    unsigned no_;
    std::string name_;
    std::string author_;
    std::string pubdate_;
};

std::istream& operator>>(std::istream&, Book&);
std::ostream& operator<<(std::ostream&, const Book&);
bool operator==(const Book&, const Book&);
bool operator!=(const Book&, const Book&);

//.cpp文件
std::istream& operator>>(std::istream &in, Book &book)
{
   
    in >> book.no_ >> book.name_ >> book.author_ >> book.pubdate_;
    return in;
}

std::ostream& operator<<(std::ostream &out, const Book &book)
{
   
    out << book.no_ << " " << book.name_ << " " << book.author_ << " " << book.pubdate_;
    return out;
}

bool operator==(const Book &lhs, const Book &rhs)
{
   
    return lhs.no_ == rhs.no_;
}

bool operator!=(const Book &lhs, const Book &rhs)
{
   
    return !(lhs == rhs);
}
//测试文件
int main()
{
   
    Book book1(001, "Test", "Andrew", "2020");
    Book book2(001, "Test", "Andrew", "2020");

    if (book1 == book2)
        std::cout << book1 << std::endl;
}

测试:1 Test Andrew 2020

练习题14.6

为你的Sales_data类定义输出运算符。

同14.2。

练习题14.7

你在13.5节的练习(P470)中曾经编写了一个String类,为它定义一个输出运算符。

//.h文件
#include <memory>
#include <iostream>
class String
{
   
    friend std::ostream& operator<<(std::ostream&, const String&);
public:
    String() : String("") {
    }
    String(const char *);
    String(const String&);
    String& operator=(const String&);
    ~String();

    const char *c_str() const {
    return elements; }
    size_t size() const {
    return end - elements; }
    size_t length() const {
    return end - elements - 1; }
private:
    std::pair<char*, char*> alloc_n_copy(const char*, const char*);
    void range_initializer(const char*, const char*);
    void free();
private:
    char *elements;
    char *end;
    std::allocator<char> alloc;
};
std::ostream& operator<<(std::ostream&, const String&);
//.cpp文件
#include <algorithm>
#include <iostream>
std::pair<char*, char*>
String::alloc_n_copy(const char *b, const char *e)
{
   
    auto str = alloc.allocate(e - b);
    return{
    str, std::uninitialized_copy(b, e, str) };
}
void String::range_initializer(const char *first, const char *last)
{
   
    auto newstr = alloc_n_copy(first, last);
    elements = newstr.first;
    end = newstr.second;
}
String::String(const char *s)
{
   
    char *sl = const_cast<char*>(s);
    while (*sl)
        ++sl;
    range_initializer(s, ++sl);
}
String::String(const String& rhs)
{
   
    range_initializer(rhs.elements, rhs.end);
    std::cout << "拷贝构造函数" << std::endl;
}
void String::free()
{
   
    if 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值