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
缺少了对错误输入情况的判断与处理,在数据成员类型不匹配时,如果无法完成转换,会导致错误的情况发生
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>}
}
没什么好说的,觉得这个版本比调用+=的省去了调用方法的消耗
缺点认为是多敲了点代码
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;
}
};
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