c++primer第五版第十四章练习

14.1

不同:重载的运算符至少有一个类类型的参数,而且不保证运算符的求值顺序,而且不再具有短路求值

相同:优先级、结合性和参数数目,这些都是不变的


14.2

friend istream &operator>>(istream &is,Sales_data &s);

friend ostream &operator<<(ostream &os,const Sales_data &s);

friend Sales_data operator+(const Sales_data &ls,const Sales_data &rs);

Sales_data &operator+=(const Sales_data &s);


14.3

a: "cobble" == "stone" 使用的是内置的==运算符,对比的是地址

b: svec1[0] == svec2[0] 使用string的==运算符,将svec1和svec2的第1个元素进行对比 string == string

c: svec1 == svec2 使用vector<string>的==运算符,vector<stting> == vecor<string>

d: svec1[0] == "stone" 使用string的==运算符,将"stone"转换为string对象,然后与svec1[0]进行对比 string == string


14.4

=,[],(),->必须为类成员,否则编译出错

复合赋值运算符通常为类成员,但并非必须

改变对象状态的运算符或者与给定类型密切的运算符,如:递增++、递减--、解引用*,通常是类成员

具有对称性的运算符可能转换任意一端的运算对象,如算术(+-*/)、相等性(== !=)、关系(><=等)和位运算(<<>>)符等,通常是普通的非成员

具有混合类型的表达式中使用对称性运算符,如:string s="primer",str="c++"+s;则运算符必须为非成员

%、<<、&&和== 建议是非成员的友元

%=和++ 通常会改变数据、建议是成员

->和()必须是成员,否则出错


14.5

#pragma once			//等同于#ifndef ..... #endif 同一头文件在同一源文件中只引用一次
#include <istream>
#include <string>
class Book
{
	std::string title;
	std::string author;
	unsigned id;
	unsigned num;
	double price;

	friend std::ostream &operator<<(std::ostream &os, const Book &b);//
	friend std::istream &operator>>(std::istream &is, Book &b);//
public:
	Book() = default;
	Book(std::string t, std::string a = "", unsigned i = 0, unsigned n = 0, double p = 0.0)
		:title(t), author(a), id(i), num(n), price(p) {}
	Book(std::istream &is)
	{
		is >> title >> author >> id >> num >> price;
	}
};


14.6

struct Sales_data
{
	std::string bookNo;
	unsigned units_sold = 0;
	double revenue = 0;

	friend std::ostream &operator<<(std::ostream &os, const Sales_data &s);//14.6

	std::string isbn()const{ return bookNo; }//const
	Sales_data &combine(const Sales_data &s);
	double avg_price()const;
};
std::ostream &operator<<(std::ostream &os, const Sales_data &s)
{
	os << s.isbn() << " " << s.units_sold << " " << s.revenue << " " << s.avg_price();
	return os;
}

14.7

class String
{
	std::allocator<char> alloc;
	char *elements;		//头
	char *first_free;	//尾后
	char *cap;			//内存尾
	void free();		//释放
	void chk_n_alloc();	//检查大小并确认是否reallocate
	void reallocate();	//增加内存
	std::pair<char *, char *> alloc_n_copy(const char *b, const char *e);	//返回创建好的副本的头和尾
public:
	String() :elements(nullptr), first_free(nullptr), cap(nullptr){}
	String(const String &s);
	String(const char *str);
	String(String &&s);	//13.49
	String &operator=(String &&s);	//13.49
	~String(){free();}
	size_t size()const{return first_free-elements;}		//返回已占用的大小
	size_t capacity()const{return cap-elements;}	//返回总大小
	char *begin()const{return elements;}
	char *end()const{return first_free;}
	friend std::ostream &operator<<(std::ostream &os, const String &s);        //14.7
	String &operator=(const String &s);
	String &operator=(const char *str);
};
std::ostream &operator<<(std::ostream &os, const String &s)
{
	os << s.begin() << std::endl;
	return os;
}

14.8

#pragma once			//等同于#ifndef ..... #endif 同一头文件在同一源文件中只引用一次
#include <istream>
#include <string>
class Book
{
	std::string title;
	std::string author;
	unsigned id;
	unsigned num;
	double price;

	friend std::ostream &operator<<(std::ostream &os, const Book &b);//14.8
	friend std::istream &operator>>(std::istream &is, Book &b);//
public:
	Book() = default;
	Book(std::string t, std::string a = "", unsigned i = 0, unsigned n = 0, double p = 0.0)
		:title(t), author(a), id(i), num(n), price(p) {}
	Book(std::istream &is)
	{
		is >> title >> author >> id >> num >> price;
	}
};
std::ostream &operator<<(std::ostream &os, const Book &b)
{
	os << b.title << " " << b.author << " " << b.id << " " << b.num << " " << b.price;
	return os;
}

14.9

#pragma once
#include <string>
class Sales_data
{
<span style="white-space:pre">	</span>std::string bookNo;
<span style="white-space:pre">	</span>unsigned units_sold = 0;
<span style="white-space:pre">	</span>double revenue = 0;


<span style="white-space:pre">	</span>friend std::ostream &operator<<(std::ostream &os, const Sales_data &s);//14.6
<span style="white-space:pre">	</span>friend std::istream &operator>>(std::istream &is, Sales_data &s);//14.9


<span style="white-space:pre">	</span>friend std::istream &read(std::istream &is, Sales_data &s);     
<span style="white-space:pre">	</span>friend std::ostream &print(std::ostream &os, const Sales_data &s);
<span style="white-space:pre">	</span>friend Sales_data add(Sales_data s1, const Sales_data &s2);
public:
<span style="white-space:pre">	</span>Sales_data() = default;
<span style="white-space:pre">	</span>Sales_data(const std::string &s) :bookNo(s){}
<span style="white-space:pre">	</span>Sales_data(const std::string &s, unsigned n, double p) :bookNo(s), units_sold(n), revenue(n*p){}
<span style="white-space:pre">	</span>Sales_data(std::istream &is)
<span style="white-space:pre">	</span>{
<span style="white-space:pre">		</span>read(is, *this);
<span style="white-space:pre">	</span>}
<span style="white-space:pre">	</span>std::string isbn(){ return bookNo; }
<span style="white-space:pre">	</span>Sales_data &combine(const Sales_data &s);
};
std::ostream &operator<<(std::ostream &os, const Sales_data &s)
{
<span style="white-space:pre">	</span>os << s.isbn() << " " << s.units_sold << " " << s.revenue << " " << s.avg_price();
<span style="white-space:pre">	</span>return os;
}
std::istream &operator>>(std::istream &is, Sales_data &s)
{
<span style="white-space:pre">	</span>auto price = s.revenue;
<span style="white-space:pre">	</span>is >> s.bookNo >> s.units_sold >> price;
<span style="white-space:pre">	</span>if (is)
<span style="white-space:pre">		</span>s.revenue = s.units_sold*price;
<span style="white-space:pre">	</span>else
<span style="white-space:pre">		</span>s = Sales_data();
<span style="white-space:pre">	</span>return is;
}

14.10

a正确:bookNo=0-201-99999-9,units_sold=10,revenue=249.5

b错误:不能将const char *转换到double,实参被设置为空的Sales_data


14.11

缺少了对错误输入情况的判断与处理,在数据成员类型不匹配时,如果无法完成转换,会导致错误的情况发生

a:正确

b:将0-201-99999-9储存到price时出错,导致revenue值错误


14.12

#pragma once			//等同于#ifndef ..... #endif 同一头文件在同一源文件中只引用一次
#include <istream>
#include <string>
class Book
{
	std::string title;
	std::string author;
	unsigned id;
	unsigned num;
	double price;

	friend std::ostream &operator<<(std::ostream &os, const Book &b);//14.8
	friend std::istream &operator>>(std::istream &is, Book &b);//14.12
public:
	Book() = default;
	Book(std::string t, std::string a = "", unsigned i = 0, unsigned n = 0, double p = 0.0)
		:title(t), author(a), id(i), num(n), price(p) {}
	Book(std::istream &is)
	{
		is >> title >> author >> id >> num >> price;
	}
};
std::ostream &operator<<(std::ostream &os, const Book &b)
{
	os << b.title << " " << b.author << " " << b.id << " " << b.num << " " << b.price;
	return os;
}
std::istream &operator>>(std::istream &is, Book &b)
{
	is >> b.title >> b.author >> b.id >> b.num >> b.price;
	if (!is)
		b = Book();
	return is;
}

14.13

#include <iostream>
#include <string>
class Sales_data
{									
	std::string bookNo;
	unsigned units_sold = 0;
	double revenue = 0;

	friend std::ostream &operator<<(std::ostream &os, const Sales_data &s);//14.6
	friend std::istream &operator>>(std::istream &is, Sales_data &s);//14.9
	friend Sales_data operator+(const Sales_data &ls, const Sales_data &rs);//14.13
	friend Sales_data operator-(const Sales_data &ls, const Sales_data &rs);//14.13

	friend std::istream &read(std::istream &is, Sales_data &s);     
	friend std::ostream &print(std::ostream &os, const Sales_data &s);
	friend Sales_data add(Sales_data s1, const Sales_data &s2);
public:
	Sales_data() = default;
	Sales_data(const std::string &s) :bookNo(s){}
	Sales_data(const std::string &s, unsigned n, double p) :bookNo(s), units_sold(n), revenue(n*p){}
	Sales_data(std::istream &is)
	{
		read(is, *this);
	}

	Sales_data &operator+=(const Sales_data &s);
	Sales_data &operator-=(const Sales_data &s);

	std::string isbn()const{ return bookNo; }
	Sales_data &combine(const Sales_data &s);
	double avg_price()const;
};
Sales_data &Sales_data::operator+=(const Sales_data &s)
{
	units_sold += s.units_sold;
	revenue += s.revenue;
	return *this;
}
Sales_data &Sales_data::operator-=(const Sales_data &s)
{
	units_sold -= s.units_sold;
	revenue -= s.revenue;
	return *this;
}
Sales_data operator+(const Sales_data &ls, const Sales_data &rs)
{
	auto temp = ls;
	temp += rs;
	return temp;
}
Sales_data operator-(const Sales_data &ls, const Sales_data &rs)
{
	auto temp = ls;
	temp -= rs;
	return temp;
}

14.14

代码重用?避免数据的暴露?反正我觉得题目有问题。

如果不是用operator+=来定义,则需要使用临时对象的各个数据成员与ls的数据成员进行相加然后返回...

觉得调用operator+=来完成操作的代价要大


14.15

#pragma once			//等同于#ifndef ..... #endif 同一头文件在同一源文件中只引用一次
#include <istream>
#include <string>
class Book
{
	std::string title;
	std::string author;
	unsigned id;
	unsigned num;
	double price;
	
	friend std::ostream &operator<<(std::ostream &os, const Book &b);//14.8
	friend std::istream &operator>>(std::istream &is, Book &b);//14.12
	friend Book operator+(const Book &lb, const Book &rb);//14.15
	friend Book operator-(const Book &lb, const Book &rb);//14.15
public:
	Book() = default;
	Book(std::string t, std::string a = "", unsigned i = 0, unsigned n = 0, double p = 0.0)
		:title(t), author(a), id(i), num(n), price(p) {}
	Book(std::istream &is)
	{
		is >> title >> author >> id >> num >> price;
	}
	Book &operator+=(const Book &b);//14.15
	Book &operator-=(const Book &b);//14.15
};
std::ostream &operator<<(std::ostream &os, const Book &b)
{
	os << b.title << " " << b.author << " " << b.id << " " << b.num << " " << b.price;
	return os;
}
std::istream &operator>>(std::istream &is, Book &b)
{
	is >> b.title >> b.author >> b.id >> b.num >> b.price;
	if (!is)
		b = Book();
	return is;
}
Book &Book::operator+=(const Book &b)
{
	this->num += b.num;
	return *this;
}
Book operator+(const Book &lb, const Book &rb)
{
	auto temp = lb;
	temp += rb;
	return temp;
}
Book &Book::operator-=(const Book &b)
{
	this->num -= b.num;
	return *this;
}
Book operator-(const Book &lb, const Book &rb)
{
	auto temp = lb;
	temp -= rb;
	return temp;
}

14.16

class StrBlob
{
	std::shared_ptr<std::vector<std::string>> data;
	void check(std::vector<std::string>::size_type i, const std::string &msg)const;
public:
	using size_type = std::vector<std::string>::size_type;
	StrBlob();
	StrBlob(std::initializer_list<std::string> il);
	bool operator==(const StrBlob &s)//14.16
	{
		return data == s.data;
	}
	bool operator!=(const StrBlob &s)//14.16
	{
		return !(*this == s);
	}
	size_type size()const;//返回vector元素数量
	bool empty()const;//是否为空
	void push_back(const std::string &t);//添加新元素到尾
	void pop_back();//弹出最后一个
	std::string front()const;
	std::string back()const;
	std::string &front();//返回第一个
	std::string &back();//返回最后一个
};

class StrBlobPtr
{
	std::shared_ptr<std::vector<std::string>> check(std::size_t, const std::string &)const;
	std::weak_ptr<std::vector<std::string>> wptr;
	std::size_t curr;
public:
	StrBlobPtr() :curr(0){}
	StrBlobPtr(StrBlob &a, std::size_t sz = 0) :wptr(a.data), curr(sz){}
	bool operator==(const StrBlobPtr &s)
	{
		return curr == s.curr&&wptr.lock() == s.wptr.lock();
	}
	bool operator!=(const StrBlobPtr &s)
	{
		return !(*this == s);
	}
	std::string &deref()const;	//解引用
	StrBlobPtr &incr();	//++n;运算符
};
class StrVec
{
	std::allocator<std::string> alloc;//为所有StrVec对象分配内存用
	void chk_n_alloc()		//如果剩余空间为0就分配新空间
	{
		if (size() == capacity())
			reallocate();
	}
	std::pair<std::string *, std::string *> alloc_n_copy(const std::string *b, const std::string *e);//创建一个内容为b到e之间的元素的对象,并返回这个对象的一对头尾指针
	void free();//释放所有alloc分配的所有内存
	void reallocate();//移动当前对象的元素到2倍对象大小的新对象里
	std::string *elements;
	std::string *first_free;
	std::string *cap;
public:
	StrVec() :elements(nullptr), first_free(nullptr), cap(nullptr){}
	StrVec(std::initializer_list<std::string> il);
	StrVec(const StrVec &s);
	StrVec(StrVec &&s);
	StrVec &operator=(StrVec &&s);
	StrVec &operator=(const StrVec &s);
	bool operator==(const StrVec &s)
	{
		if (size() != s.size())
			return false;
		auto it = elements, its = s.elements;
		while (it != first_free)
		{
			if (*it++ != *its++)
				return false;
		}
		return true;
	}
	bool operator!=(const StrVec &s)
	{
		return !(*this == s);
	}
	~StrVec();
	void push_back(const std::string &s);//把string添加到尾后指针
	size_t size()const
	{
		return first_free - elements;
	}
	size_t capacity()const
	{
		return cap - elements;
	}
	std::string *begin()const
	{
		return elements;
	}
	std::string *end()const
	{
		return first_free;
	}
};
class String
{
	std::allocator<char> alloc;
	char *elements;		//头
	char *first_free;	//尾后
	char *cap;			//内存尾
	void free();		//释放
	void chk_n_alloc();	//检查大小并确认是否reallocate
	void reallocate();	//增加内存
	std::pair<char *, char *> alloc_n_copy(const char *b, const char *e);	//返回创建好的副本的头和尾
public:
	String() :elements(nullptr), first_free(nullptr), cap(nullptr){}
	String(const String &s);
	String(const char *str);
	String(String &&s);	//13.49
	String &operator=(String &&s);	//13.49
	bool operator==(const String &s)
	{
		if (size() != s.size())
			return false;
		auto it = elements, its = s.elements;
		while (it != first_free)
		{
			if (*it++ != *its++)
				return false;
		}
		return true;
	}
	bool operator!=(const String &s)
	{
		return !(*this == s);
	}
	~String(){free();}
	size_t size()const{return first_free-elements;}		//返回已占用的大小
	size_t capacity()const{return cap-elements;}	//返回总大小
	char *begin()const{return elements;}
	char *end()const{return first_free;}
	friend std::ostream &operator<<(std::ostream &os, const String &s);//14.7
	String &operator=(const String &s);
	String &operator=(const char *str);
};

14.17

class Book
{
	std::string title;
	std::string author;
	unsigned id;
	unsigned num;
	double price;
	
	friend std::ostream &operator<<(std::ostream &os, const Book &b);//14.8
	friend std::istream &operator>>(std::istream &is, Book &b);//14.12
	friend Book operator+(const Book &lb, const Book &rb);//14.15
	friend Book operator-(const Book &lb, const Book &rb);//14.15
public:
	Book() = default;
	Book(std::string t, std::string a = "", unsigned i = 0, unsigned n = 0, double p = 0.0)
		:title(t), author(a), id(i), num(n), price(p) {}
	Book(std::istream &is)
	{
		is >> title >> author >> id >> num >> price;
	}
	Book &operator+=(const Book &b);//14.15
	Book &operator-=(const Book &b);//14.15
	bool operator==(const Book &b)
	{
		return (title == b.title)&&
			(author == b.author)&&
			(id == b.id)&&
			(num = b.num)&&
			(price == b.price);
	}
	bool operator!=(const Book &b)
	{
		return !(*this == b);
	}
};


14.18

class StrBlob
{
<span style="white-space:pre">	</span>std::shared_ptr<std::vector<std::string>> data;
<span style="white-space:pre">	</span>void check(std::vector<std::string>::size_type i, const std::string &msg)const;
public:
<span style="white-space:pre">	</span>using size_type = std::vector<std::string>::size_type;
<span style="white-space:pre">	</span>StrBlob();
<span style="white-space:pre">	</span>StrBlob(std::initializer_list<std::string> il);
<span style="white-space:pre">	</span>bool operator==(const StrBlob &s)//14.16
<span style="white-space:pre">	</span>{
<span style="white-space:pre">		</span>return data == s.data;
<span style="white-space:pre">	</span>}
<span style="white-space:pre">	</span>bool operator!=(const StrBlob &s)//14.16
<span style="white-space:pre">	</span>{
<span style="white-space:pre">		</span>return !(*this == s);
<span style="white-space:pre">	</span>}
<span style="white-space:pre">	</span>bool operator<(const StrBlob &s)//14.18
<span style="white-space:pre">	</span>{
<span style="white-space:pre">		</span>return data < s.data;
<span style="white-space:pre">	</span>}
<span style="white-space:pre">	</span>bool operator>(const StrBlob &s)//14.18
<span style="white-space:pre">	</span>{
<span style="white-space:pre">		</span>return !(*this < s) && *this != s;
<span style="white-space:pre">	</span>}
<span style="white-space:pre">	</span>bool operator<=(const StrBlob &s)//14.18
<span style="white-space:pre">	</span>{
<span style="white-space:pre">		</span>return !(*this > s);
<span style="white-space:pre">	</span>}
<span style="white-space:pre">	</span>bool operator>=(const StrBlob &s)//14.18
<span style="white-space:pre">	</span>{
<span style="white-space:pre">		</span>return !(*this < s);
<span style="white-space:pre">	</span>}
<span style="white-space:pre">	</span>size_type size()const;//返回vector元素数量
<span style="white-space:pre">	</span>bool empty()const;//是否为空
<span style="white-space:pre">	</span>void push_back(const std::string &t);//添加新元素到尾
<span style="white-space:pre">	</span>void pop_back();//弹出最后一个
<span style="white-space:pre">	</span>std::string front()const;
<span style="white-space:pre">	</span>std::string back()const;
<span style="white-space:pre">	</span>std::string &front();//返回第一个
<span style="white-space:pre">	</span>std::string &back();//返回最后一个
};
class StrBlobPtr
{
<span style="white-space:pre">	</span>std::shared_ptr<std::vector<std::string>> check(std::size_t, const std::string &)const;
<span style="white-space:pre">	</span>std::weak_ptr<std::vector<std::string>> wptr;
<span style="white-space:pre">	</span>std::size_t curr;
public:
<span style="white-space:pre">	</span>StrBlobPtr() :curr(0){}
<span style="white-space:pre">	</span>StrBlobPtr(StrBlob &a, std::size_t sz = 0) :wptr(a.data), curr(sz){}
<span style="white-space:pre">	</span>bool operator==(const StrBlobPtr &s)//14.16
<span style="white-space:pre">	</span>{
<span style="white-space:pre">		</span>return curr == s.curr&&wptr.lock() == s.wptr.lock();
<span style="white-space:pre">	</span>}
<span style="white-space:pre">	</span>bool operator!=(const StrBlobPtr &s)//14.16
<span style="white-space:pre">	</span>{
<span style="white-space:pre">		</span>return !(*this == s);
<span style="white-space:pre">	</span>}
<span style="white-space:pre">	</span>bool operator<(const StrBlobPtr &s)//14.18
<span style="white-space:pre">	</span>{
<span style="white-space:pre">		</span>return curr < s.curr&&wptr.lock() < s.wptr.lock();
<span style="white-space:pre">	</span>}
<span style="white-space:pre">	</span>bool operator>(const StrBlobPtr &s)//14.18
<span style="white-space:pre">	</span>{
<span style="white-space:pre">		</span>return !(*this < s) && *this != s;
<span style="white-space:pre">	</span>}
<span style="white-space:pre">	</span>bool operator<=(const StrBlobPtr &s)//14.18
<span style="white-space:pre">	</span>{
<span style="white-space:pre">		</span>return !(*this > s);
<span style="white-space:pre">	</span>}
<span style="white-space:pre">	</span>bool operator>=(const StrBlobPtr &s)//1.18
<span style="white-space:pre">	</span>{
<span style="white-space:pre">		</span>return !(*this < s);
<span style="white-space:pre">	</span>}
<span style="white-space:pre">	</span>std::string &deref()const;<span style="white-space:pre">	</span>//解引用
<span style="white-space:pre">	</span>StrBlobPtr &incr();<span style="white-space:pre">	</span>//++n;运算符
};
class StrVec
{
<span style="white-space:pre">	</span>std::allocator<std::string> alloc;//为所有StrVec对象分配内存用
<span style="white-space:pre">	</span>void chk_n_alloc()<span style="white-space:pre">		</span>//如果剩余空间为0就分配新空间
<span style="white-space:pre">	</span>{
<span style="white-space:pre">		</span>if (size() == capacity())
<span style="white-space:pre">			</span>reallocate();
<span style="white-space:pre">	</span>}
<span style="white-space:pre">	</span>std::pair<std::string *, std::string *> alloc_n_copy(const std::string *b, const std::string *e);//创建一个内容为b到e之间的元素的对象,并返回这个对象的一对头尾指针
<span style="white-space:pre">	</span>void free();//释放所有alloc分配的所有内存
<span style="white-space:pre">	</span>void reallocate();//移动当前对象的元素到2倍对象大小的新对象里
<span style="white-space:pre">	</span>std::string *elements;
<span style="white-space:pre">	</span>std::string *first_free;
<span style="white-space:pre">	</span>std::string *cap;
public:
<span style="white-space:pre">	</span>StrVec() :elements(nullptr), first_free(nullptr), cap(nullptr){}
<span style="white-space:pre">	</span>StrVec(std::initializer_list<std::string> il);
<span style="white-space:pre">	</span>StrVec(const StrVec &s);
<span style="white-space:pre">	</span>StrVec(StrVec &&s);
<span style="white-space:pre">	</span>StrVec &operator=(StrVec &&s);
<span style="white-space:pre">	</span>StrVec &operator=(const StrVec &s);
<span style="white-space:pre">	</span>bool operator==(const StrVec &s)//14.16
<span style="white-space:pre">	</span>{
<span style="white-space:pre">		</span>if (size() != s.size())
<span style="white-space:pre">			</span>return false;
<span style="white-space:pre">		</span>auto it = elements, its = s.elements;
<span style="white-space:pre">		</span>while (it != first_free)
<span style="white-space:pre">		</span>{
<span style="white-space:pre">			</span>if (*it++ != *its++)
<span style="white-space:pre">				</span>return false;
<span style="white-space:pre">		</span>}
<span style="white-space:pre">		</span>return true;
<span style="white-space:pre">	</span>}
<span style="white-space:pre">	</span>bool operator!=(const StrVec &s)//14.16
<span style="white-space:pre">	</span>{
<span style="white-space:pre">		</span>return !(*this == s);
<span style="white-space:pre">	</span>}
<span style="white-space:pre">	</span>bool operator<(const StrVec &s)//14.18
<span style="white-space:pre">	</span>{
<span style="white-space:pre">		</span>if (size()>s.size())
<span style="white-space:pre">			</span>return false;
<span style="white-space:pre">		</span>else if (size() < s.size)
<span style="white-space:pre">			</span>return true;
<span style="white-space:pre">		</span>for (auto it = elements, its = s.elements; it != first_free; ++it, ++its)
<span style="white-space:pre">		</span>{
<span style="white-space:pre">			</span>if (*it == *its)
<span style="white-space:pre">				</span>continue;
<span style="white-space:pre">			</span>else if (*it > *its)
<span style="white-space:pre">				</span>return false;
<span style="white-space:pre">			</span>else
<span style="white-space:pre">				</span>return true;
<span style="white-space:pre">		</span>}
<span style="white-space:pre">		</span>return false;
<span style="white-space:pre">	</span>}
<span style="white-space:pre">	</span>bool operator>(const StrVec &s)//14.18
<span style="white-space:pre">	</span>{
<span style="white-space:pre">		</span>return !(*this < s) && *this != s;
<span style="white-space:pre">	</span>}
<span style="white-space:pre">	</span>bool operator<=(const StrVec &s)//14.18
<span style="white-space:pre">	</span>{
<span style="white-space:pre">		</span>return !(*this > s);
<span style="white-space:pre">	</span>}
<span style="white-space:pre">	</span>bool operator>=(const StrVec &s)//14.18
<span style="white-space:pre">	</span>{
<span style="white-space:pre">		</span>return !(*this < s);
<span style="white-space:pre">	</span>}
<span style="white-space:pre">	</span>~StrVec();
<span style="white-space:pre">	</span>void push_back(const std::string &s);//把string添加到尾后指针
<span style="white-space:pre">	</span>size_t size()const
<span style="white-space:pre">	</span>{
<span style="white-space:pre">		</span>return first_free - elements;
<span style="white-space:pre">	</span>}
<span style="white-space:pre">	</span>size_t capacity()const
<span style="white-space:pre">	</span>{
<span style="white-space:pre">		</span>return cap - elements;
<span style="white-space:pre">	</span>}
<span style="white-space:pre">	</span>std::string *begin()const
<span style="white-space:pre">	</span>{
<span style="white-space:pre">		</span>return elements;
<span style="white-space:pre">	</span>}
<span style="white-space:pre">	</span>std::string *end()const
<span style="white-space:pre">	</span>{
<span style="white-space:pre">		</span>return first_free;
<span style="white-space:pre">	</span>}
};
class String
{
<span style="white-space:pre">	</span>std::allocator<char> alloc;
<span style="white-space:pre">	</span>char *elements;<span style="white-space:pre">		</span>//头
<span style="white-space:pre">	</span>char *first_free;<span style="white-space:pre">	</span>//尾后
<span style="white-space:pre">	</span>char *cap;<span style="white-space:pre">			</span>//内存尾
<span style="white-space:pre">	</span>void free();<span style="white-space:pre">		</span>//释放
<span style="white-space:pre">	</span>void chk_n_alloc();<span style="white-space:pre">	</span>//检查大小并确认是否reallocate
<span style="white-space:pre">	</span>void reallocate();<span style="white-space:pre">	</span>//增加内存
<span style="white-space:pre">	</span>std::pair<char *, char *> alloc_n_copy(const char *b, const char *e);<span style="white-space:pre">	</span>//返回创建好的副本的头和尾
public:
<span style="white-space:pre">	</span>String() :elements(nullptr), first_free(nullptr), cap(nullptr){}
<span style="white-space:pre">	</span>String(const String &s);
<span style="white-space:pre">	</span>String(const char *str);
<span style="white-space:pre">	</span>String(String &&s);<span style="white-space:pre">	</span>//13.49
<span style="white-space:pre">	</span>String &operator=(String &&s);<span style="white-space:pre">	</span>//13.49
<span style="white-space:pre">	</span>bool operator==(const String &s)
<span style="white-space:pre">	</span>{
<span style="white-space:pre">		</span>if (size() != s.size())
<span style="white-space:pre">			</span>return false;
<span style="white-space:pre">		</span>auto it = elements, its = s.elements;
<span style="white-space:pre">		</span>while (it != first_free)
<span style="white-space:pre">		</span>{
<span style="white-space:pre">			</span>if (*it++ != *its++)
<span style="white-space:pre">				</span>return false;
<span style="white-space:pre">		</span>}
<span style="white-space:pre">		</span>return true;
<span style="white-space:pre">	</span>}
<span style="white-space:pre">	</span>bool operator!=(const String &s)
<span style="white-space:pre">	</span>{
<span style="white-space:pre">		</span>return !(*this == s);
<span style="white-space:pre">	</span>}
<span style="white-space:pre">	</span>bool operator<(const String &s)
<span style="white-space:pre">	</span>{
<span style="white-space:pre">		</span>if (size()>s.size())
<span style="white-space:pre">			</span>return false;
<span style="white-space:pre">		</span>else if (size() < s.size)
<span style="white-space:pre">			</span>return true;
<span style="white-space:pre">		</span>for (auto it = elements, its = s.elements; it != first_free; ++it, ++its)
<span style="white-space:pre">		</span>{
<span style="white-space:pre">			</span>if (*it == *its)
<span style="white-space:pre">				</span>continue;
<span style="white-space:pre">			</span>else if (*it > *its)
<span style="white-space:pre">				</span>return false;
<span style="white-space:pre">			</span>else
<span style="white-space:pre">				</span>return true;
<span style="white-space:pre">		</span>}
<span style="white-space:pre">		</span>return false;
<span style="white-space:pre">	</span>}
<span style="white-space:pre">	</span>bool operator>(const String &s)
<span style="white-space:pre">	</span>{
<span style="white-space:pre">		</span>return !(*this < s) && *this != s;
<span style="white-space:pre">	</span>}
<span style="white-space:pre">	</span>bool operator<=(const String &s)
<span style="white-space:pre">	</span>{
<span style="white-space:pre">		</span>return !(*this > s);
<span style="white-space:pre">	</span>}
<span style="white-space:pre">	</span>bool operator>=(const String &s)
<span style="white-space:pre">	</span>{
<span style="white-space:pre">		</span>return !(*this < s);
<span style="white-space:pre">	</span>}
<span style="white-space:pre">	</span>~String(){free();}
<span style="white-space:pre">	</span>size_t size()const{return first_free-elements;}<span style="white-space:pre">		</span>//返回已占用的大小
<span style="white-space:pre">	</span>size_t capacity()const{return cap-elements;}<span style="white-space:pre">	</span>//返回总大小
<span style="white-space:pre">	</span>char *begin()const{return elements;}
<span style="white-space:pre">	</span>char *end()const{return first_free;}
<span style="white-space:pre">	</span>friend std::ostream &operator<<(std::ostream &os, const String &s);//14.7
<span style="white-space:pre">	</span>String &operator=(const String &s);
<span style="white-space:pre">	</span>String &operator=(const char *str);
};

14.19

class Book
{
	std::string title;
	std::string author;
	unsigned id;
	unsigned num;
	double price;
	
	friend std::ostream &operator<<(std::ostream &os, const Book &b);//14.8
	friend std::istream &operator>>(std::istream &is, Book &b);//14.12
	friend Book operator+(const Book &lb, const Book &rb);//14.15
	friend Book operator-(const Book &lb, const Book &rb);//14.15
public:
	Book() = default;
	Book(std::string t, std::string a = "", unsigned i = 0, unsigned n = 0, double p = 0.0)
		:title(t), author(a), id(i), num(n), price(p) {}
	Book(std::istream &is)
	{
		is >> title >> author >> id >> num >> price;
	}
	Book &operator+=(const Book &b);//14.15
	Book &operator-=(const Book &b);//14.15
	bool operator==(const Book &b)//14.17
	{
		return (title == b.title)&&
			(author == b.author)&&
			(id == b.id)&&
			(num = b.num)&&
			(price == b.price);
	}
	bool operator!=(const Book &b)//14.17
	{
		return !(*this == b);
	}
	bool operator<(const Book &b)
	{
		return num < b.num;
	}
	bool operator>(const Book &b)
	{
		return !(*this < b) && *this != b;
	}
	bool operator<=(const Book &b)
	{
		return !(*this > b);
	}
	bool operator>=(const Book &b)
	{
		return !(*this < b);
	}
};

14.20
class Sales_data
{
	std::string bookNo;
	unsigned units_sold = 0;
	double revenue = 0;

	friend std::ostream &operator<<(std::ostream &os, const Sales_data &s);//14.6
	friend std::istream &operator>>(std::istream &is, Sales_data &s);//14.9
	friend Sales_data operator+(const Sales_data &ls, const Sales_data &rs);//14.13
	friend Sales_data operator-(const Sales_data &ls, const Sales_data &rs);//14.13

	friend std::istream &read(std::istream &is, Sales_data &s);
	friend std::ostream &print(std::ostream &os, const Sales_data &s);
	friend Sales_data add(Sales_data s1, const Sales_data &s2);
public:
	Sales_data() = default;
	Sales_data(const std::string &s) :bookNo(s) {}
	Sales_data(const std::string &s, unsigned n, double p) :bookNo(s), units_sold(n), revenue(n*p) {}
	Sales_data(std::istream &is)
	{
		read(is, *this);
	}
	Sales_data &operator+=(const Sales_data &s);
	Sales_data &operator-=(const Sales_data &s);
	Sales_data &operator=(const Sales_data &s)//14.20
	{
		bookNo = s.bookNo;
		units_sold = s.units_sold;
		revenue = s.revenue;
		return *this;
	}
	std::string isbn()const { return bookNo; }
	Sales_data &combine(const Sales_data &s);
	double avg_price()const;
};

14.21
class Sales_data
{
<span style="white-space:pre">	</span>//.....
<span style="white-space:pre">	</span>Sales_data operator+(const Sales_data &ls, const Sales_data &rs)
<span style="white-space:pre">	</span>{
<span style="white-space:pre">		</span>auto temp = ls;
<span style="white-space:pre">		</span>temp.units_sold += rs.units_sold;
<span style="white-space:pre">		</span>temp.revenue += rs.revenue;
<span style="white-space:pre">		</span>return temp;
<span style="white-space:pre">	</span>}
}

没什么好说的,觉得这个版本比调用+=的省去了调用方法的消耗

缺点认为是多敲了点代码


14.22
class Sales_data
{
<span style="white-space:pre">	</span>//.....
<span style="white-space:pre">	</span>Sales_data &operator=(const std::string &s)//14.22
<span style="white-space:pre">	</span>{
<span style="white-space:pre">		</span>bookNo = s;
<span style="white-space:pre">		</span>return *this;
<span style="white-space:pre">	</span>}
}

14.23

class StrVec
{
	std::allocator<std::string> alloc;//为所有StrVec对象分配内存用
	void chk_n_alloc()		//如果剩余空间为0就分配新空间
	{
		if (size() == capacity())
			reallocate();
	}
	std::pair<std::string *, std::string *> alloc_n_copy(const std::string *b, const std::string *e);//创建一个内容为b到e之间的元素的对象,并返回这个对象的一对头尾指针
	void free();//释放所有alloc分配的所有内存
	void reallocate();//移动当前对象的元素到2倍对象大小的新对象里
	std::string *elements;
	std::string *first_free;
	std::string *cap;
public:
	StrVec() :elements(nullptr), first_free(nullptr), cap(nullptr){}
	StrVec(std::initializer_list<std::string> il);
	StrVec(const StrVec &s);
	StrVec(StrVec &&s);
	StrVec &operator=(StrVec &&s);
	StrVec &operator=(const StrVec &s);
	bool operator==(const StrVec &s)//14.16
	{
		if (size() != s.size())
			return false;
		auto it = elements, its = s.elements;
		while (it != first_free)
		{
			if (*it++ != *its++)
				return false;
		}
		return true;
	}
	bool operator!=(const StrVec &s)//14.16
	{
		return !(*this == s);
	}
	bool operator<(const StrVec &s)//14.18
	{
		if (size()>s.size())
			return false;
		else if (size() < s.size)
			return true;
		for (auto it = elements, its = s.elements; it != first_free; ++it, ++its)
		{
			if (*it == *its)
				continue;
			else if (*it > *its)
				return false;
			else
				return true;
		}
		return false;
	}
	bool operator>(const StrVec &s)//14.18
	{
		return !(*this < s) && *this != s;
	}
	bool operator<=(const StrVec &s)//14.18
	{
		return !(*this > s);
	}
	bool operator>=(const StrVec &s)//14.18
	{
		return !(*this < s);
	}
	StrVec &operator=(std::initializer_list<std::string> il)//14.23
	{
		auto nobj = alloc_n_copy(il.begin(), il.end());
		free();
		elements = nobj.first;
		first_free = cap = nobj.second;
		return *this;
	}
	~StrVec();
	void push_back(const std::string &s);//把string添加到尾后指针
	size_t size()const
	{
		return first_free - elements;
	}
	size_t capacity()const
	{
		return cap - elements;
	}
	std::string *begin()const
	{
		return elements;
	}
	std::string *end()const
	{
		return first_free;
	}
};


14.24
class Book
{
	std::string title;
	std::string author;
	unsigned id;
	unsigned num;
	double price;
	
	friend std::ostream &operator<<(std::ostream &os, const Book &b);//14.8
	friend std::istream &operator>>(std::istream &is, Book &b);//14.12
	friend Book operator+(const Book &lb, const Book &rb);//14.15
	friend Book operator-(const Book &lb, const Book &rb);//14.15
public:
	Book() = default;
	Book(std::string t, std::string a = "", unsigned i = 0, unsigned n = 0, double p = 0.0)
		:title(t), author(a), id(i), num(n), price(p) {}
	Book(std::istream &is)
	{
		is >> title >> author >> id >> num >> price;
	}
	Book &operator+=(const Book &b);//14.15
	Book &operator-=(const Book &b);//14.15
	bool operator==(const Book &b)//14.17
	{
		return (title == b.title)&&
			(author == b.author)&&
			(id == b.id)&&
			(num = b.num)&&
			(price == b.price);
	}
	bool operator!=(const Book &b)//14.17
	{
		return !(*this == b);
	}
	bool operator<(const Book &b)
	{
		return num < b.num;
	}
	bool operator>(const Book &b)
	{
		return !(*this < b) && *this != b;
	}
	bool operator<=(const Book &b)
	{
		return !(*this > b);
	}
	bool operator>=(const Book &b)
	{
		return !(*this < b);
	}
	Book &operator=(const Book &s)//14.24
	{
		title = s.title;
		author = s.author;
		id = s.id;
		price = s.price;
		num = s.num;
		return *this;
	}
};

14.25

不需要,书还能怎么玩?


14.26

class StrBlob
{
<span style="white-space:pre">	</span>//....
<span style="white-space:pre">	</span>std::string &operator[](std::size_t n)
	{
		return data->at(n);
	}
	const std::string &operator[](std::size_t n)const
	{
		return data->at(n);
	}
}
class StrBlobPtr
{
<span style="white-space:pre">	</span>//...
<span style="white-space:pre">	</span>std::string &operator[](std::size_t n)
	{
		return wptr.lock()->at(n);
	}
	const std::string &operator[](std::size_t n)const {
		return wptr.lock()->at(n);
	}
}
class StrVec
{
<span style="white-space:pre">	</span>//...
<span style="white-space:pre">	</span>std::string &operator[](std::size_t n)
	{
		return elements[n];
	}
	const std::string &operator[](std::size_t n)const
	{
		return elements[n];
	}
}
class String
{
<span style="white-space:pre">	</span>//...
<span style="white-space:pre">	</span>char &operator[](std::size_t n)
	{
		return elements[n];
	}
	const char &operator[](std::size_t n)const
	{
		return elements[n];
	}
}


14.27
clas StrBlobPtr
{
<span style="white-space:pre">	</span>//...
<span style="white-space:pre">	</span>StrBlobPtr &operator++()
	{
		check(curr, "increment past end of StrBlobPtr");
		++curr;
		return *this;
	}
	StrBlobPtr &operator--()
	{
		--curr;
		check(curr, "decrement past begin of StrBlobPtr");
		return *this;
	}
	StrBlobPtr operator++(int)
	{
		auto ret = *this;
		++*this;
		return ret;
	}
	StrBlobPtr operator--(int)
	{
		auto ret = *this;
		--*this;
		return ret;
	}
}

14.28

class StrBlobPtr
{
<span style="white-space:pre">	</span>//...
<span style="white-space:pre">	</span>StrBlobPtr operator+(std::size_t n)
	{
		auto ret = *this;
		ret.curr += n;
		return ret;
	}
	StrBlobPtr operator-(std::size_t n)
	{
		auto ret = *this;
		ret.curr -= n;
		return ret;
	}
}

14.29

都说是const


14.30

class StrBlobPtr
{
<span style="white-space:pre">	</span>//...
<span style="white-space:pre">	</span>std::string &operator*()const
	{
		auto p = check(curr, "dereference past end");
		return (*p)[curr];
	}
	std::string *operator->()const
	{
		return &this->operator*();
	}
}
class ConstStrBlobPtr
{
<span style="white-space:pre">	</span>//...
<span style="white-space:pre">	</span>const std::string &operator*()const
	{
		auto p = check(curr, "dereference past end");
		return (*p)[curr];
	}
	const std::string *operator->()const
	{
		return &this->operator*();
	}
}

14.31

规则3/5说道,没有进行动态内存的分配情况下,合成的析构函数足以销毁所有成员

拷贝构造与赋值运算符合成版本就可以满足需求:复制值对象


14.32

class sptr
{
	StrBlobPtr *ptr;
public:
	StrBlobPtr &operator*()const {
		return *ptr;
	}
	StrBlobPtr *operator->()const {
		return &this->operator*();
	}
};

14.33

与重载的函数成员的参数数量一样(最大好像是256左右)


14.34

class fobj
{
	int operator()(bool b, int ia, int ib)
	{
		if (b)return ia;
		else return ib;
	}
};

14.35

class EnterString
{
	std::string operator()(std::istream &is = std::cin)
	{
		std::string temp;
		getline(is, temp);
		if (is)
			return temp;
		else
			return std::string();
	}
};

14.36

#include <iostream>
#include <string>
#include <vector>
class EnterString
{
public:
	std::string operator()(std::istream &is = std::cin)
	{
		std::string temp;
		getline(is, temp);
		if (is)
			return temp;
		else
			return std::string();
	}
};

int main()
{
	using namespace std;
	vector<string> vec;
	EnterString en;
	while (cin)
	{
		vec.push_back(en(cin));
	}
	for (auto x : vec)
		cout << x << endl;
	system("pause");
	return 0;
}

14.37

#include <iostream>
#include <algorithm>
#include <string>
class isEqual
{
	char val;
public:
	isEqual(char ch = ' ') :val(ch) {}
	bool operator()(char ch)
	{
		return ch == val;
	}
};
int main()
{
	using namespace std;
	//相当于调用了一个isEqual ie('a'); if(ie(*iter))*iter='@';	//如果当前char等于ie保存的'a',那么替换为@
	string str = "osufofjakhiowpaouhwaqjkgtuwyqoiljkzaaloifhbkjqwgbazkdfsefwaauwqaahakjuwrwqirha";
	replace_if(str.begin(), str.end(), isEqual('a'), '@');
	cout << str << endl;
	system("pause");
	return 0;
}

14.38

#include <iostream>
#include <string>
#include <vector>
#include <fstream>
class strn
{
	std::size_t n;
public:
	strn(std::size_t i = 0) :n(i) {}
	bool operator()(const std::string &s)
	{
		return n == s.size();
	}
};
int main(int argc, char **argv)
{
	using namespace std;
	ifstream ifile(argv[1]);
	if (!ifile)exit(1);
	vector<int> num(10,0);
	vector<strn> vec(10);
	for (int i = 1; i <= 10; ++i)
		vec.push_back(i);
	string temp;
	while (ifile >> temp)
	{
		for (auto &x : vec)
		{
			if (x(temp))
			{
				++num[temp.size()-1];
				break;
			}
		}
	}
	for (auto n : num)
		cout << n << " ";
	return 0;
}

14.39

#include <iostream>
#include <string>
#include <vector>
#include <fstream>
class strn
{
	std::size_t n;
	std::size_t m;
public:
	strn(std::size_t i = 1,std::size_t j=100) :n(i),m(j) {}
	bool operator()(const std::string &s)
	{
		return n <= s.size()&&m>=s.size();
	}
};
int main(int argc, char **argv)
{
	using namespace std;
	ifstream ifile(argv[1]);
	if (!ifile)exit(1);
	vector<int> num(2, 0);
	vector<strn> vec(2);
	vec[0] = strn(0, 9);
	vec[1] = strn(10);
	string temp;
	while (ifile >> temp)
	{
		for (auto &x : vec)
		{
			if (x(temp))
			{
				if (temp.size() <= 9)
					++num[0];
				else
					++num[1];
				break;
			}
		}
	}
	for (auto n : num)
		cout << n << " ";
	return 0;
}

14.40

#include <iostream>
#include <vector>
#include <algorithm>	//sort unique stable_sort find_if for_each
#include <string>
void elimDups(std::vector<std::string> &vstr)
{
	sort(vstr.begin(), vstr.end());	//默认排序
	auto u_end = unique(vstr.begin(), vstr.end());	//删除连续相同的元素
	vstr.erase(u_end, vstr.end());	//清理空元素
}
class issize
{
	std::size_t n;
public:
	issize(std::size_t i) :n(i) {}
	bool operator()(const std::string &s)
	{
		return s.size() >= n;
	}
};
class towstrequal
{
public:
	bool operator()(const std::string &s1, const std::string &s2)
	{
		return s1.size() < s2.size(); 
	}
};
void biggies(std::vector<std::string> &s, std::vector<std::string>::size_type sz)
{
	elimDups(s);
	stable_sort(s.begin(), s.end(), towstrequal());	//长度相同的单词按字典排序
	auto wc = find_if(s.begin(), s.end(), issize(sz));	//记录第一次大小大于sz的位置
	auto count = s.end() - wc;	//统计元素尾到wc的位置的距离
	std::cout << count << " " << (sz ? "word" : "s") << " of length " << sz << " or longer" << std::endl;
	for_each(wc, s.end(), [](const std::string &s){std::cout << s << "\t"; });
	std::cout << std::endl;
}
int main()
{
	using namespace std;
	vector<string> vstr = { "c++", "false", "string", "delete", "c++", "string", "visual", "studio", "c++", "basic", "true", "system", "delete" };
	elimDups(vstr);
	for (auto s : vstr)
		cout << s << endl;
	system("pause");
	return 0;
}

14.41

方便使用,方便创建,不需要额为的为调用对象声明类

在一次性需要使用函数对象时使用lambda,在多次需要使用到相同的函数对象时使用类


14.42

#include <algorithm>
#include <vector>
#include <string>
#include <iostream>
#include <functional>
int main()
{
	using namespace std;
	vector<int> ivec{1554,215,645,2145,1024,5145,3654,1024,51,512,102,1024,56145,1024,545};
									//大于
							//绑定1024到greater<int>函数对象的第二个参数,并返回一个一元谓词
	int count = count_if(ivec.begin(), ivec.end(), bind(greater<int>(),placeholders::_1, 1024));//统计1024的出现次数
	cout << count << endl;

	vector<string> svec{ "pooh","pooh","pooh","java","pooh","teacher" };
									//不等于
							//绑定"pooh"到notequal<string>函数对象的第二个参数,并返回一个一元谓词
	auto found = find_if(svec.begin(), svec.end(), bind(not_equal_to<string>(), placeholders::_1, "pooh"));//找到第一个非"pooh"的迭代期位置
	cout << *found << endl;

	vector<int> iivec(ivec.size());				<span style="white-space:pre">	</span>//相乘
							//绑定2到multiplies<int>函数对象的第二个参数,把该函数对象返回的值替换iivec的元素
	transform(ivec.begin(), ivec.end(), iivec.begin(),bind(multiplies<int>(), placeholders::_1, 2));//把ivec中所有的元素*2然后保存到iivec
	for (auto x : iivec)
		cout << x << " ";
	system("pause");
	return 0;
}

14.43

#include <iostream>
#include <algorithm>
#include <vector>
int main()
{
	using namespace std;
	vector<int> vec{ 45,60,90,75,30,15,105 };
	int temp;
	cin >> temp;
	modulus<int> mod;
<span style="white-space:pre">	</span>auto func = [&](int i) {return mod(i,temp); };//返回i%temp的值
	if (any_of(vec.begin(), vec.end(), func))//如果全部元素执行对象func都是false就返回false,所以这里是如果所有元素都能整除temp就返回false
		cout << "all the elements can not be divisible";

	system("pause");
	return 0;
}

14.44

#include <iostream>
#include <functional>
#include <string>
#include <map>
int add(int a, int b)
{
	return a + b;
}
class divide
{
public:
	int operator()(int a, int b)
	{
		return a / b;
	}
};
int main()
{
	using namespace std;
	auto mod = [](int a, int b) {return a%b; };
	map<string, function<int(int, int)>> binops =
	{
		{"+",add},
		{"-",minus<int>()},
		{"*",[](int a,int b) {return a*b; }},
		{"/",divide()},
		{"%",mod}
	};
	int a, b;
	char ch;
	while (cin >> a >> ch >> b)
	{
		cout << a << ch << b << "=" << binops[string(1, ch)](a, b) << endl;
	}
	system("pause");
	return 0;
}

14.45

#pragma once
#include <iostream>
#include <string>
struct Sales_data
{
	std::string bookNo;
	unsigned units_sold = 0;
	double revenue = 0;

	friend std::ostream &operator<<(std::ostream &os, const Sales_data &s);//14.6
	explicit operator std::string()const {//string
		return bookNo;
	}
	explicit operator double()const {//double
		return revenue;
	}
<span style="white-space:pre">	</span>std::string isbn()const { return bookNo; }//const
	Sales_data &combine(const Sales_data &s);
	double avg_price()const;
};

14.46

不是太理想,因为可能会让人误导,例如operator double,到底是转换出价钱还是销量(unsigned)

应该添加,这样就可以明确的说明只有在对应为double时才转换



14.47

operator const int()没有意义

operator int()const表示转换时不会修改对象数据


14.48

需要,可以是确定书本的存货是否为空

应该是explicit,防止发送隐式转换


14.49

class Book
{
	//...
	explicit operator bool()const
	{
		return num;
	}

}

14.50

ex1二义性,double和float都可以转换为int

ex2精确匹配float


14.51

最佳的是calc(int);

会引起转换为类类型的级别比它低

匹配顺序(大雾):
  精确匹配 //最佳
  const转换
  类型提升
  算术或指针转换
  类类型转换 //最低


14.52

ld=si+ld;二义性,si将转换为int,但ld可以转换为double也可以使float

ld=ld+si;精确匹配LongDouble operator+(const SmallInt &);,虽然使用后面的也可以,但是需要转换,所以前者更好


14.53

double d=s1+3.14; 二义性:算术+算术和SmallInt+SmallInt都可以

为了不丢失精度,改为:double d=double(s1)+3.14更好






2015年12月17日 21:38:14



你可能感兴趣的:(练习,答案,C++primer第五版,c++prmer)