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; }
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; }
#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; }
#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; }
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; }
#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; }
代码重用?避免数据的暴露?反正我觉得题目有问题。
如果不是用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; }
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); };
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); } };
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; };
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.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]; } }
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; } }
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; } }
都说是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*(); } };
与重载的函数成员的参数数量一样(最大好像是256左右)
14.34
class fobj { int operator()(bool b, int ia, int ib) { if (b)return ia; else return ib; } };
class EnterString { std::string operator()(std::istream &is = std::cin) { std::string temp; getline(is, temp); if (is) return temp; else return std::string(); } };
#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; }
#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; }
#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; }
#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; }
方便使用,方便创建,不需要额为的为调用对象声明类
在一次性需要使用函数对象时使用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; }
#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; }
#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; };
不是太理想,因为可能会让人误导,例如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; } }
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