C++ Primer第五版_第十四章习题答案(1~10)
文章目录
-
-
- 练习14.1
- 练习14.2
-
- 头文件
- CPP文件
- 练习14.3
- 练习14.4
- 练习14.5
-
- 头文件
- CPP文件
- 练习14.6
- 练习14.7
-
- 头文件
- CPP文件
- 练习14.8
- 练习14.9
- 练习14.10
-
练习14.1
在什么情况下重载的运算符与内置运算符有所区别?在什么情况下重载的运算符又与内置运算符一样?
我们可以直接调用重载运算符函数。重置运算符与内置运算符有一样的优先级与结合性。
练习14.2
为 Sales_data 编写重载的输入、输出、加法和复合赋值运算符。
头文件
#ifndef CP5_CH14_EX14_02_H
#define CP5_CH14_EX14_02_H#include <string>
#include <iostream>class Sales_data
{friend std::istream& operator>>(std::istream&, Sales_data&); // inputfriend std::ostream& operator<<(std::ostream&, const Sales_data&); // outputfriend Sales_data operator+(const Sales_data&, const Sales_data&); // additionpublic: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-assignmentstd::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;
}#endif // CP5_CH14_EX14_02_H
CPP文件
#include "exercise14_2.h"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;elseitem = 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;
}
练习14.3
string 和 vector 都定义了重载的以比较各自的对象,假设 svec1 和 svec2 是存放 string 的 vector,确定在下面的表达式中分别使用了哪个版本的?
(a) "cobble" == "stone"
(b) svec1[0] == svec2[0]
(c) svec1 == svec2
(d) "svec1[0] == "stone"
- (a) 都不是。
- (b) string
- © vector
- (d) string
练习14.4
如何确定下列运算符是否应该是类的成员?
(a) %
(b) %=
(c) ++
(d) ->
(e) <<
(f) &&
(g) ==
(h) ()
- (a) 不需要是成员。
- (b) 是成员。
- © 是成员。
- (d) 必须是成员。
- (e) 不需要是成员。
- (f) 不需要是成员。
- (g) 不需要是成员。
- (h) 必须是成员。
练习14.5
在7.5.1节中的练习7.40中,编写了下列类中某一个的框架,请问在这个类中应该定义重载的运算符吗?如果是,请写出来。
(a) Book
(b) Date
(c) Employee
(d) Vehicle
(e) Object
(f) Tree
头文件
#ifndef CP5_CH14_EX14_05_H
#define CP5_CH14_EX14_05_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&);#endif // CP5_CH14_EX14_05_H
CPP文件
#include "exercise14_5.h"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);
}
练习14.6
为你的 Sales_data 类定义输出运算符。
练习14.7
你在13.5节的练习中曾经编写了一个String类,为它定义一个输出运算符。
头文件
#ifndef CP5_CH14_EX07_H_
#define CP5_CH14_EX07_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&);#endif //CP5_CH14_EX07_H_
CPP文件
#include "exercise14_7.h"
#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 << "copy constructor" << std::endl;
}void String::free()
{if (elements){std::for_each(elements, end, [this](char &c) { alloc.destroy(&c); });alloc.deallocate(elements, end - elements);}
}String::~String()
{free();
}String& String::operator = (const String &rhs)
{auto newstr = alloc_n_copy(rhs.elements, rhs.end);free();elements = newstr.first;end = newstr.second;std::cout << "copy-assignment" << std::endl;return *this;
}std::ostream& operator<<(std::ostream &os, const String &s)
{char *c = const_cast<char*>(s.c_str());while (*c)os << *c++;return os;
}
练习14.8
你在7.5.1节中的练习中曾经选择并编写了一个类,为它定义一个输出运算符。
练习14.9
为你的 Sales_data 类定义输入运算符。
练习14.10
对于 Sales_data 的输入运算符来说如果给定了下面的输入将发生什么情况?
(a) 0-201-99999-9 10 24.95
(b) 10 24.95 0-210-99999-9
- (a) 格式正确。
- (b) 不合法的输入。因为程序试图将
0-210-99999-9
转换为float
。