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

18.1

*p解引用后是r,所以两者都是range_error对象

因为是throw p,如果没有匹配的catch,那么将调用terminate,程序将终止


18.2

v是vector对象,将调用自己的析构函数

指针p被释放,但是p所指向的内存将丢失

调用自己的析构函数,关闭文件


18.3

1、使用类对象的方法,创建一个包含一个int*的类,在析构函数进行delete文件指针

[cpp]  view plain  copy
  1. class intAr  
  2. {  
  3.     int *p=nullptr;  
  4. public:  
  5.     intAr(size_t n):p(new int[n]){}  
  6.     ~intAr()  
  7.     {  
  8.         delete[]p;  
  9.     }  
  10. }  

intAr p(v.size());,那么p对象就可以在发生异常时调用析构函数delete所分配的内存了

2、使用智能指针,自动控制

[cpp]  view plain  copy
  1. std::shared_ptr<int> p(new int[v.size()], [](int *p) { delete[] p; });  
使用lambda表达式创建一个函数对象给智能指针的构造函数,在发生异常时自动调用并delete内存


18.4

第一个catch就是基类,那么所有该基类的派生类都可以匹配,因为不是引用或指针,那么将丢弃基类以为的部分

第二个catch也是,runtime_error派生出overflow_error,能匹配runtime_error和voerflw_error,所以当发生overflow_error异常时总是使用runtime_error

[cpp]  view plain  copy
  1. try {  
  2.     //  
  3. }  
  4. catch (overflow_error e)  
  5. {  
  6.     //...  
  7. }  
  8. catch (const runtime_error &r)  
  9. {  
  10.     //...  
  11. }  
  12. catch (exception e)  
  13. {  
  14.     //...  
  15. }  

18.5

[cpp]  view plain  copy
  1. #include <iostream>  
  2. #include <cstdlib>  
  3. int main()  
  4. {  
  5.     using namespace std;  
  6.     try {  
  7.         //  
  8.     }  
  9.     catch (overflow_error e)  
  10.     {  
  11.         cout << e.what();  
  12.         abort();  
  13.     }  
  14.     catch (underflow_error u)  
  15.     {  
  16.         cout << u.what();  
  17.         abort();  
  18.     }  
  19.     catch (range_error r)  
  20.     {  
  21.         cout << r.what();  
  22.         abort();  
  23.     }  
  24.     catch (domain_error d)  
  25.     {  
  26.         cout << d.what();  
  27.         abort();  
  28.     }  
  29.     catch (invalid_argument i)  
  30.     {  
  31.         cout << i.what();  
  32.         abort();  
  33.     }  
  34.     catch (out_of_range o)  
  35.     {  
  36.         cout << o.what();  
  37.         abort();  
  38.     }  
  39.     catch (length_error l)  
  40.     {  
  41.         cout << l.what();  
  42.         abort();  
  43.     }  
  44.     catch (runtime_error r)  
  45.     {  
  46.         cout << r.what();  
  47.         abort();  
  48.     }  
  49.     catch (logic_error l)  
  50.     {  
  51.         cout << l.what();  
  52.         abort();  
  53.     }  
  54.     catch (bad_alloc b)  
  55.     {  
  56.         cout << b.what();  
  57.         abort();  
  58.     }  
  59.     catch (bad_alloc b)  
  60.     {  
  61.         cout << b.what();  
  62.         abort();  
  63.     }  
  64.     catch (exception e)  
  65.     {  
  66.         cout << e.what();  
  67.         abort();  
  68.     }  
  69.   
  70.     return 0;  
  71. }  


18.6
a、throw &exceptionType();

b、任何异常都行

c、throw int();

应该没错..


18.7

[cpp]  view plain  copy
  1. #pragma once  
  2. #include <iostream>  
  3. #include <string>  
  4. #include <vector>  
  5. #include <initializer_list>  
  6. #include <memory> //shared_ptr  
  7. template<typename T> class Blob;  
  8. template<typename T> class BlobPtr;  
  9. template<typename T> bool operator==(const Blob<T>&, const Blob<T>&);  
  10. template<typename T>  
  11. class Blob  
  12. {  
  13. public:  
  14.     friend class BlobPtr<T>;  
  15.     friend bool operator==<T>(const Blob &l, const Blob &r);  
  16.     typedef T value_type;  
  17.     typedef typename std::vector<T>::size_type size_type; //把size_type视为类型名,忽略vector里同名的(如果有)静态变量  
  18.     Blob();  
  19.     Blob(std::initializer_list<T> il);  
  20.     template<class U>  
  21.     Blob(U b, U e);  
  22.     size_type size()const {                     //返回元素数量  
  23.         return data->size();  
  24.     }  
  25.     bool empty()const {                         //是否为空  
  26.         return data->empty();  
  27.     }  
  28.     void push_back(const T &t) {                //添加元素到末尾  
  29.         data->push_back(t);  
  30.     }  
  31.     void push_back(T &&t) {  
  32.         data->push_back(std::move(t));  
  33.     }  
  34.     void pop_back();                            //弹出末尾元素  
  35.     T &back();                                  //返回末尾元素的引用  
  36.     T &operator[](size_type i);                 //返回第i个元素的引用  
  37. private:  
  38.     std::shared_ptr<std::vector<T>> data;  
  39.     void check(size_type i, const std::string &msg)const;  
  40. };  
  41.   
  42. template<typename T>  
  43. void Blob<T>::check(size_type i, const std::string &msg)const {  
  44.     if (i >= data->size())  
  45.         throw std::out_of_range(msg);  
  46. }  
  47. template<typename T>  
  48. T &Blob<T>::back() {  
  49.     check(0, "back on empty Blob");  
  50.     return data->back();  
  51. }  
  52. template<typename T>  
  53. T &Blob<T>::operator[](size_type i) {  
  54.     check(i, "subscript out range");  
  55.     return (*data)[i];  
  56. }  
  57. template<typename T>  
  58. void Blob<T>::pop_back() {  
  59.     check(0, "pop_back on empty Blob");  
  60.     data->pop_back();  
  61. }  
  62. template<typename T>  
  63. Blob<T>::Blob() try:data(std::make_shared<std::vector<T>>()) {  
  64. }  
  65. catch (const std::bad_alloc &e) {  
  66.     std::cerr << e.what() << std::endl;  
  67. }  
  68. template<typename T>  
  69. Blob<T>::Blob(std::initializer_list<T> il) try : data(std::make_shared<std::vector<T>>(il)) {  
  70. }  
  71. catch (const std::bad_alloc &e) {  
  72.     std::cerr << e.what() << std::endl;  
  73. }  
  74.   
  75. template<typename T>  
  76. bool operator==(const Blob<T> &l, const Blob<T> &r) {  
  77.     if (l.data != r.data)  
  78.         return false;  
  79.     return true;  
  80. }  
  81.   
  82. template<class T>  
  83. template<class U>  
  84. Blob<T>::Blob(U b, U e) :data(std::make_shared < std::vector<T>>(b, e)) {}  

[cpp]  view plain  copy
  1. //BlobPtr.h  
  2. #pragma once  
  3. #include "Blob.h"  
  4. template<typename T>  
  5. class BlobPtr {  
  6. public:  
  7.     BlobPtr();  
  8.     BlobPtr(Blob<T> &a, size_t sz = 0);  
  9.     T &operator*()const;  
  10.     BlobPtr &operator++();  
  11.     BlobPtr &operator--();  
  12. private:  
  13.     std::shared_ptr<std::vector<T>> check(std::size_t i, const std::string &s)const;  
  14.     std::weak_ptr<std::vector<T>> wptr;  
  15.     std::size_t curr;  
  16. };  
  17. template<typename T>  
  18. BlobPtr<T>::BlobPtr() try :curr(0) {  
  19. }  
  20. catch(const std::bad_alloc &e){  
  21.     std::cerr << e.what() << std::endl;  
  22. }  
  23.   
  24. template<typename T>  
  25. BlobPtr<T>::BlobPtr(Blob<T> &a, size_t sz /* = 0 */try : wptr(a.data), curr(sz) {  
  26. }  
  27. catch (const std::bad_alloc &e) {  
  28.     std::cerr << e.what() << std::endl;  
  29. }  
  30.   
  31. template<typename T>  
  32. T &BlobPtr<T>::operator*()const {  
  33.     auto p = check(curr, "dereference past end");  
  34.     return (*p)[curr];  
  35. }  
  36.   
  37. template<typename T>  
  38. BlobPtr<T> &BlobPtr<T>::operator++() {  
  39.     ++curr;  
  40.     check(curr, "++obj error");  
  41.     return *this;  
  42. }  
  43.   
  44. template<typename T>  
  45. BlobPtr<T> &BlobPtr<T>::operator--() {  
  46.     --curr;  
  47.     if (curr < 0)  
  48.         throw std::out_of_range("--obj error");  
  49.     return *this;  
  50. }  
  51.   
  52. template<typename T>  
  53. std::shared_ptr<std::vector<T>> BlobPtr<T>::check(std::size_t i, const std::string &s)const {  
  54.     auto ret = wptr.lock();                                 //确认未被释放内存  
  55.     if (!ret)  
  56.         throw std::out_of_range("unbound BlobPtr");  
  57.     if (i >= ret->size())  
  58.         throw std::out_of_range(s);  
  59.     return ret;  
  60. }  

18.8

略,别问我为什么


18.9

[cpp]  view plain  copy
  1. #pragma once  
  2. #include <iostream>  
  3. #include <string>  
  4. //18.9  
  5. struct out_of_stock :public std::runtime_error  
  6. {  
  7.     explicit out_of_stock(const std::string &s) :std::runtime_error(s) {}  
  8. };  
  9.   
  10. struct isbn_mismatch :public std::logic_error  
  11. {  
  12.     explicit isbn_mismatch(const std::string &s) :std::logic_error(s) {}  
  13.     isbn_mismatch(const std::string &s, const std::string &ls, const std::string &rs)  
  14.         :std::logic_error(s), left(ls), right(rs)  
  15.     {}  
  16.     std::string left;  
  17.     std::string right;  
  18. };  

[cpp]  view plain  copy
  1. #pragma once  
  2. #include "error_class.h"  
  3. class Sales_data  
  4. {  
  5.     std::string bookNo;  
  6.     unsigned units_sold = 0;  
  7.     double revenue = 0.0;  
  8.     double avg_price() const;  
  9. public:  
  10.     Sales_data() = default;  
  11.     Sales_data(const std::string &s) : bookNo(s) {}  
  12.     Sales_data(const std::string &s, unsigned n, double p) :  
  13.         bookNo(s), units_sold(n), revenue(p*n) {}  
  14.     explicit Sales_data(std::istream &is) { is >> *this; }  
  15.     std::string isbn() const { return bookNo; }  
  16.     Sales_data& operator+=(const Sales_data&);  
  17.     Sales_data& operator=(const std::string&);  
  18.   
  19.     friend std::ostream &operator<<(std::ostream&, const Sales_data&);  
  20.     friend std::istream &operator>>(std::istream&, Sales_data&);  
  21.     friend Sales_data operator+(const Sales_data&, const Sales_data&);  
  22.     friend bool operator==(const Sales_data&, const Sales_data&);  
  23.     friend bool operator!=(const Sales_data&, const Sales_data&);  
  24.     friend Sales_data operator+(const Sales_data&, const Sales_data&);  
  25. };  
  26.   
  27. Sales_data& Sales_data::operator+=(const Sales_data& rhs)  
  28. {  
  29.     if (isbn() != rhs.isbn())//18.9  
  30.         throw isbn_mismatch("wrong isbns", isbn(), rhs.isbn());//如果书名不相同,触发异常  
  31.     units_sold += rhs.units_sold;  
  32.     revenue += rhs.revenue;  
  33.     return *this;  
  34. }  
  35. Sales_data& Sales_data::operator=(const std::string &isbn)  
  36. {  
  37.     bookNo = isbn;  
  38.     return *this;  
  39. }  
  40.   
  41. inline double Sales_data::avg_price() const  
  42. {  
  43.     if (units_sold != 0)  
  44.         return revenue / units_sold;  
  45.     else  
  46.         return revenue;  
  47. }  
  48.   
  49. std::ostream& operator<<(std::ostream& os, const Sales_data& item)  
  50. {  
  51.     os << item.bookNo << " "  
  52.         << item.units_sold << " "  
  53.         << item.revenue << " "  
  54.         << item.avg_price();  
  55.     return os;  
  56. }  
  57.   
  58. std::istream& operator>>(std::istream &is, Sales_data& item)  
  59. {  
  60.     double price = 0;  
  61.     is >> item.bookNo >> item.units_sold >> price;  
  62.     if (is)  
  63.         item.revenue = item.units_sold * price;  
  64.     else  
  65.         item = Sales_data();  
  66.     return is;  
  67. }  
  68. bool operator==(const Sales_data &lhs, const Sales_data &rhs)  
  69. {  
  70.     return lhs.bookNo == rhs.bookNo &&  
  71.         lhs.units_sold == rhs.units_sold &&  
  72.         lhs.revenue == rhs.revenue;  
  73. }  
  74. bool operator!=(const Sales_data &lhs, const Sales_data &rhs)  
  75. {  
  76.     return !(lhs == rhs);  
  77. }  
  78. Sales_data operator+(const Sales_data &lhs, const Sales_data &rhs)  
  79. {  
  80.     Sales_data sum = lhs;  
  81.     sum += rhs;  
  82.     return sum;  
  83. }  


[cpp]  view plain  copy
  1. #include "Sales_data.h"  
  2. //18.9  
  3. int main()  
  4. {  
  5.     using namespace std;  
  6.     Sales_data item1("book1",10,23.3), item2("book2",6,66.6), sum;  
  7.     cout<<item1 + item2;//18.10\1  
  8.   
  9.   
  10.     while (cin >> item1 >> item2)  
  11.     {  
  12.         try {//18.10/2  
  13.             sum = item1 + item2;  
  14.         }  
  15.         catch (const isbn_mismatch &e)  
  16.         {  
  17.             cout << e.what() << ": left isbn(" << e.left << ") right isbn(" << e.right << ")" << endl;  
  18.         }  
  19.         cout << "book:\n" << sum << endl;  
  20.     }  
  21.     system("pause");  
  22.     return 0;  
  23. }  

未捕获的异常会调用terminate,导致程序结束


18.11

引用 “心不在焉”的话:

what函数一般是在catch语句中被调用的,
try/catch本来有加个保险的作用
如果what里面抛个异常,尼玛try/catch还有什么用,
难道每个catch里面都要再加个try/catch,
这不是坑人吗

https://segmentfault.com/q/1010000004968342?_ea=740379


18.12

[cpp]  view plain  copy
  1. #pragma once  
  2. //ch10.h  
  3. #include <initializer_list>  
  4. #include <iostream>  
  5. #include <fstream>    //ifstream  
  6. #include <string>  
  7. #include <vector>  
  8. #include <sstream>    //istringstream  
  9. #include <map>  
  10. #include <set>  
  11. #include <memory> //shared_ptr  
  12. namespace chapter10  
  13. {  
  14.     class StrBlob  
  15.     {  
  16.         std::shared_ptr<std::vector<std::string>> data;  
  17.         void check(std::vector<std::string>::size_type i, const std::string &msg)const;  
  18.     public:  
  19.         using size_type = std::vector<std::string>::size_type;  
  20.         StrBlob();  
  21.         StrBlob(std::initializer_list<std::string> il);  
  22.         size_type size()const;//返回vector元素数量  
  23.         bool empty()const;//是否为空  
  24.         void push_back(const std::string &t);//添加新元素到尾  
  25.         void pop_back();//弹出最后一个  
  26.         std::string front()const;  
  27.         std::string back()const;  
  28.         std::string &front();//返回第一个  
  29.         std::string &back();//返回最后一个  
  30.         const std::shared_ptr<std::vector<std::string>> &shared_ptr()const  //返回data的const引用  
  31.         {  
  32.             return data;  
  33.         }  
  34.     };  
  35.   
  36.     class QueryResult;  
  37.     class TextQuery  
  38.     {  
  39.   
  40.         std::shared_ptr<StrBlob> file;                            //保存整个文件内容,按行分  
  41.         std::map<std::string, std::shared_ptr<std::set<StrBlob::size_type>>> wm;  //每个单词对应行号  
  42.     public:  
  43.         using line_no = std::vector<std::string>::size_type;  
  44.         TextQuery(std::ifstream &is);  
  45.         QueryResult query(const std::string &s)const;                   //返回QR,单词、行号set,还有关联到文件内容  
  46.     };  
  47.     class QueryResult  
  48.     {  
  49.         friend std::ostream &print(std::ostream &os, const QueryResult &qr);  
  50.         std::string sought;  
  51.         std::shared_ptr<std::set<StrBlob::size_type>> lines;                        //记录出现的行号  
  52.         std::shared_ptr<StrBlob> file;                                    //关联到文件内容  
  53.     public:  
  54.         std::set<StrBlob::size_type>::iterator begin()const {  
  55.             return lines->begin();  
  56.         }  
  57.         std::set<StrBlob::size_type>::iterator end()const {  
  58.             return lines->end();  
  59.         }  
  60.         std::shared_ptr<StrBlob> get_file()const {  
  61.             return file;  
  62.         }  
  63.         QueryResult(std::string s, const std::shared_ptr<std::set<StrBlob::size_type>> &p, std::shared_ptr<StrBlob> f) :sought(s), lines(p), file(f) {}  
  64.     };  
  65. }  

[cpp]  view plain  copy
  1. #pragma once  
  2. //ch15.h  
  3. #include <algorithm>  //set_intersection  
  4. #include <iterator>       //inserter  
  5. #include "ch10.h"  
  6. namespace chapter15  
  7. {  
  8.     using namespace chapter10;  
  9.     class Query_base  
  10.     {  
  11.         friend class Query;  
  12.         virtual QueryResult eval(const TextQuery &tq)const = 0;  
  13.         virtual std::string rep()const = 0;  
  14.     protected:  
  15.         using line_no = TextQuery::line_no;  
  16.         virtual ~Query_base() = default;  
  17.     };  
  18.     class Query  
  19.     {  
  20.         friend Query operator~(const Query &qy);  
  21.         friend Query operator|(const Query &lhs, const Query &rhs);  
  22.         friend Query operator&(const Query &lhs, const Query &rhs);  
  23.         std::shared_ptr<Query_base> q;  
  24.         Query(std::shared_ptr<Query_base> qptr) :q(qptr) { std::cout << "Query(std::shared_ptr<Query_base>)\n"; }  
  25.     public:  
  26.         Query(const std::string &s);  
  27.         QueryResult eval(const TextQuery &t)const {  
  28.             return q->eval(t);  
  29.         }  
  30.         std::string rep()const {  
  31.             std::cout << "Query rep()\n";  
  32.             return q->rep();  
  33.         }  
  34.     };  
  35. }  

[cpp]  view plain  copy
  1. #include "ch15.h"  
  2. //file.cpp  
  3. namespace chapter10  
  4. {  
  5.     void StrBlob::check(std::vector<std::string>::size_type i, const std::string &msg)const  
  6.     {  
  7.         if (i >= data->size())  
  8.             throw std::out_of_range(msg);  
  9.     }  
  10.     StrBlob::StrBlob() :data(std::make_shared<std::vector<std::string>>())  
  11.     {}  
  12.     StrBlob::StrBlob(std::initializer_list<std::string> il) : data(std::make_shared<std::vector<std::string>>(il))  
  13.     {}  
  14.     StrBlob::size_type StrBlob::size()const  
  15.     {  
  16.         return data->size();  
  17.     }  
  18.     bool StrBlob::empty()const  
  19.     {  
  20.         return data->empty();  
  21.     }  
  22.     void StrBlob::push_back(const std::string &t)  
  23.     {  
  24.         data->push_back(t);  
  25.     }  
  26.     void StrBlob::pop_back()  
  27.     {  
  28.         check(0, "pop_push on empty StrBlob");  
  29.         data->pop_back();  
  30.     }  
  31.     std::string &StrBlob::front()  
  32.     {  
  33.         check(0, "front on empty StrBlob");  
  34.         return data->front();  
  35.     }  
  36.     std::string &StrBlob::back()  
  37.     {  
  38.         check(0, "back on empty StrBlob");  
  39.         return data->back();  
  40.     }  
  41.     std::string StrBlob::front()const  
  42.     {  
  43.         return data->front();  
  44.     }  
  45.     std::string StrBlob::back()const  
  46.     {  
  47.         return data->back();  
  48.     }  
  49.   
  50.   
  51.     TextQuery::TextQuery(std::ifstream &is) :file(new StrBlob())    //为智能指针file分配空间  
  52.     {  
  53.         std::string text;  
  54.         while (getline(is, text))  
  55.         {  
  56.             file->push_back(text);  
  57.             int n = file->size() - 1;  
  58.             std::istringstream line(text);  
  59.             std::string word;  
  60.             while (line >> word)  
  61.             {  
  62.                 auto &lines = wm[word];                     //如果word在wm中第一次出现,那么对应的set就未分配内存,所以为空  
  63.                 if (!lines)                                     //如果第一次出现  
  64.                     lines.reset(new std::set<StrBlob::size_type>);  
  65.                 lines->insert(n);  
  66.             }  
  67.         }  
  68.     }  
  69.   
  70.     QueryResult TextQuery::query(const std::string &s)const  
  71.     {  
  72.         static std::shared_ptr<std::set<StrBlob::size_type>> nodata(new std::set<StrBlob::size_type>);    //当没找到单词时返回 内存常驻  
  73.         auto loc = wm.find(s);  
  74.         if (loc == wm.end())  
  75.             return QueryResult(s, nodata, file);  
  76.         else  
  77.             return QueryResult(s, loc->second, file);  
  78.     }  
  79.   
  80.     std::ostream &print(std::ostream &os, const QueryResult &qr)  
  81.     {  
  82.         os << qr.sought << " occurs " << qr.lines->size() << " " << (qr.lines->size() > 1 ? "times" : "time") << std::endl;  
  83.         for (auto x : *qr.lines)  
  84.             os << "\t(line " << x + 1 << ") " << qr.file->shared_ptr()->at(x) << std::endl;     //StrBlob需要添加返回data const引用的方法  
  85.         return os;  
  86.     }  
  87.   
  88. }  
  89.   
  90. namespace chapter15  
  91. {  
  92.     std::ostream &operator<<(std::ostream &os, const Query query)  
  93.     {  
  94.         return os << query.rep();  
  95.     }  
  96.     class WordQuery :public Query_base  
  97.     {  
  98.         friend class Query;  
  99.         std::string query_word;  
  100.         WordQuery(const std::string s) :query_word(s) { std::cout << "WordQuery(const std::string s)\n"; }  
  101.         QueryResult eval(const TextQuery &t)const {  
  102.             return t.query(query_word);  
  103.         }  
  104.         std::string rep()const {  
  105.             std::cout << "WordQuery rep()\n";  
  106.             return query_word;  
  107.         }  
  108.     };  
  109.     Query::Query(const std::string &s) :q(new WordQuery(s)) { std::cout << "Query(const std::string &s)\n"; }  
  110.     class NotQuery :public Query_base  
  111.     {  
  112.         friend Query operator~(const Query &q);  
  113.         Query query;  
  114.         NotQuery(const Query &qy) :query(qy) { std::cout << "NotQuery(const Query &qy)\n"; }  
  115.         std::string rep()const {  
  116.             std::cout << "NotQuery rep()\n";  
  117.             return "~(" + query.rep() + ")";  
  118.         }  
  119.         QueryResult eval(const TextQuery &t)const;  
  120.     };  
  121.     Query operator~(const Query &q)  
  122.     {  
  123.         return std::shared_ptr<Query_base>(new NotQuery(q));  
  124.     }  
  125.     class BinaryQuery :public Query_base  
  126.     {  
  127.     protected:  
  128.         Query lhs, rhs;  
  129.         std::string opSym;  
  130.         BinaryQuery(const Query &l, const Query &r, std::string s) :lhs(l), rhs(r), opSym(s) { std::cout << "BinaryQuery(const Query &l, const Query &r, std::string s)\n"; }  
  131.         std::string rep()const {  
  132.             std::cout << "BinaryQuery rep()\n";  
  133.             return "(" + lhs.rep() + " " + opSym + " " + rhs.rep() + ")";  
  134.         }  
  135.     };  
  136.     class AndQuery :public BinaryQuery  
  137.     {  
  138.         friend Query operator&(const Query &lhq, const Query &rhq);  
  139.         AndQuery(const Query &left, const Query &right) :BinaryQuery(left, right, "&") { std::cout << "AndQuery(const Query &left, const Query &right)\n"; }  
  140.         QueryResult eval(const TextQuery &t)const;  
  141.     };  
  142.     Query operator&(const Query &lhs, const Query &rhs)  
  143.     {  
  144.         return std::shared_ptr<Query_base>(new AndQuery(lhs, rhs));  
  145.     }  
  146.     class OrQuery :public BinaryQuery  
  147.     {  
  148.         friend Query operator|(const Query &lhs, const Query &rhs);  
  149.         OrQuery(const Query &left, const Query &right) :BinaryQuery(left, right, "|") { std::cout << "OrQuery(const Query &left, const Query &right)\n"; }  
  150.         QueryResult eval(const TextQuery &tq)const;  
  151.     };  
  152.     Query operator|(const Query &lhs, const Query &rhs)  
  153.     {  
  154.         return std::shared_ptr<Query_base>(new OrQuery(lhs, rhs));  
  155.     }  
  156.     QueryResult OrQuery::eval(const TextQuery &tq)const  
  157.     {  
  158.         auto right = rhs.eval(tq), left = lhs.eval(tq);  
  159.         auto ret_lines = std::make_shared<std::set<line_no>>(left.begin(), left.end());  
  160.         ret_lines->insert(right.begin(), right.end());  
  161.         return QueryResult(rep(), ret_lines, left.get_file());  
  162.     }  
  163.     QueryResult AndQuery::eval(const TextQuery &t)const  
  164.     {  
  165.         auto left = lhs.eval(t), right = rhs.eval(t);  
  166.         auto ret_lines = std::make_shared<std::set<line_no>>();  
  167.         std::set_intersection(left.begin(), left.end(), right.begin(), right.end(), inserter(*ret_lines, ret_lines->begin()));//求出集合A和集合B相同的元素  
  168.         return QueryResult(rep(), ret_lines, left.get_file());  
  169.     }  
  170.     QueryResult NotQuery::eval(const TextQuery &t)const  
  171.     {  
  172.         auto result = query.eval(t);  
  173.         auto ret_line = std::make_shared<std::set<line_no>>();  
  174.         auto beg = result.begin(), end = result.end();  
  175.         auto sz = result.get_file()->size();  
  176.         for (size_t n = 0; n != sz; ++n)  
  177.         {  
  178.             if (beg == end || *beg != n)  
  179.                 ret_line->insert(n);  
  180.             else if (beg != end)  
  181.                 ++beg;  
  182.         }  
  183.         return QueryResult(rep(), ret_line, result.get_file());  
  184.     }  
  185. }  

[cpp]  view plain  copy
  1. #include "ch15.h"  
  2. int main(int argc, char **argv)  
  3. {  
  4.     using namespace std;  
  5.     using namespace chapter10;  
  6.     using namespace chapter15;  
  7.     ifstream ifile(argv[1]);  
  8.     print(cout, (Query("nono") | Query("ika")).eval(ifile)) << endl;  
  9.     system("pause");  
  10.     return 0;  
  11. }  

18.13

希望所定义的对象、函数、类类型或其他实体,只在程序的一小段代码中可见,这样可以进一步的缓解名字空间的冲突。
根据c++11标准,static定义静态变量的做法已取消,现在是定义一个全局的未命名的名字空间。
在未命名的名字空间中定义的变量都是静态的。


18.14

mathLib::MatrixLib::matrix mathLib::MatrixLib::operator*(matrix &a,matrix &b);


18.15

using声明:将某个成员的名字引入作用域,让该名字在该作用域可见

using指示:把名字空间的全部成员在该作用域可见


18.16、18.17

[cpp]  view plain  copy
  1. #include <iostream>  
  2. namespace exercise {  
  3.     int ivar = 0;  
  4.     double dvar = 0;  
  5.     const int limi = 1000;  
  6. }  
  7. int ivar = 0;  
  8.   
  9. //1.1  
  10. //using exercise::ivar;//错误,与全局变量ivar冲突,多次声明  
  11. //using exercise::dvar;  
  12. //using exercise::limi;  
  13. //  
  14. //void manip()  
  15. //{  
  16. //  double dvar = 3.1416;//覆盖using声明的dvar  
  17. //  int iobj = limi + 1;  
  18. //  ++ivar;  
  19. //  ++::ivar;  
  20. //}  
  21.   
  22.   
  23. //1.2  
  24. //void manip()  
  25. //{  
  26. //  using exercise::ivar;//隐藏全局变量  
  27. //  using exercise::dvar;  
  28. //  using exercise::limi;  
  29. //  double dvar = 3.1416;//错误,多重定义,多次初始化,当前dvar对象已经可见  
  30. //  int iobj = limi + 1;  
  31. //  ++ivar;//exercise的ivar  
  32. //  ++::ivar;//全局变量  
  33. //}  
  34.   
  35. //2.1  
  36. //using namespace exercise;  
  37. //void manip()  
  38. //{  
  39. //  double dvar = 3.1416;//覆盖using声明的dvar  
  40. //  int iobj = limi + 1;  
  41. //  ++ivar;//错误,不明确,二义性,二者都可见  
  42. //  ++::ivar;  
  43. //}  
  44.   
  45. //2.2  
  46. //void manip()  
  47. //{  
  48. //  using namespace exercise;  
  49. //  double dvar = 3.1416;//覆盖using声明的dvar  
  50. //  int iobj = limi + 1;  
  51. //  ++ivar;//错误,不明确,二义性,二者都可见  
  52. //  ++::ivar;  
  53. //}  
  54. int main(){  
  55.     system("pause");  
  56.     return 0;  
  57. }  

18.18

当meml是string时:

当前作用域-找到std::swap-参数string-使用string类的swap

当meml是int时:

当前作用域-找到std::swap,实例化出int型,结束

两者的不同就是string使用的是自己的swap


18.19

那么就是使用std的swap了,因为限定了是使用std的,所以string版本就直接在std里寻找,int也是直接实例化int的swap版本


18.20

1

namespace p
{
	void compute();//不可行
	void compute(const void *);//可行,0->NULL
}
using p::compute;
void compute(int);//可行,最佳匹配
void compute(double, double = 1.1);//可行,int->double
void compute(char*, char* = 0);//可行,0->NULL

void f()
{
	compute(0);//与compute(int)版本最佳匹配
}

2
#include <iostream>
namespace p{
	void compute();//不可行,不可见
	void compute(const void *);//可行,0->NULL,不可见
}
void compute(int);//可行,最佳匹配
void compute(double, double = 1.1);//可行,int->double
void compute(char*, char* = 0);//可行,0->NULL
void f(){
	
	compute(0);//与compute(int)版本最佳匹配
}
int main(){
	using p::compute;
	f();
	return 0;
}

18.21
a、无错误,公有继承CAD,私有继承Vehicle,
b、错误,继承列表重复,多次继承List,如果是不同的List,则需要使用名字空间区分,如A():public C::List,public D::List{}
c、无错误,公有继承于标准输入与标准输出库

18.22
首先构造C,而C是派生与A和B的,所以A与B构造完后构造C
然后构造Z,而Z是派生于X与Y的,所以X与Y构造完后构造Z
所以顺序是:A->B->C->x->Y->Z->MI

18.23
无错误,所有直接基类或基类的基类都可以指向该派生类对象
#include <iostream>
using std::cout;
using std::endl;
class A {
public:
	A() { cout << "A()" << endl; }
};
class B : public A {
public:
	B() : A() { cout << "B()" << endl; }
};
class C : public B {
public:
	C() : B() { cout << "C()" << endl; }
};
class X {
public:
	X() { cout << "X()" << endl; }
};
class D : public X, public C {};
int main()
{
	D *pd = new D;
	X *px = pd;
	A *pa = pd;
	B *pb = pd;
	C *pc = pd;
	delete pd;
	system("pause");
	return 0;
}

18.24
ZooAnimal *pd=new Panda("ying_ying");
pd->print();//正确,Panda::print()
pd->cuddle();//错误,ZooAnimal无此成员
pd->highlight();//错误,ZooAnimal无此成员
delete pd;//正确,~Panda()

18.25
a、Base1::print
b、D1::print
c、D2::print
d、Base2::~Base2
e、D1::~D1
f、D2::~D2

18.26
因为MI类定义了一个自己的print成员,所以覆盖了继承的print,所以找不到接受int的print
解决方法是在MI里定义一个接受int的print,并显示调用Base1::print(int):
struct MI :public Derived, public Base2 {
	void print(std::vector<double>)const;
	void print(int a) { Base1::print(a); }//显示调用基类的print(int)
protected:
	int *ival;
	std::vector<double> dvec;
};

18.27
a、可以见的:
Base1:ival、dval、cval、print
Base2:fval、print
Derived:sval、dval、print
MI:ival、dvec、print、foo
还有在foo里定义的ival
b、是:
dval:Base1::dval、Derived::dval、自己定义的int dval
ival :MI::ival、Base1::ival
cval:Base1::cval、形参cval
print:Base1:print、Base2::print、Derived::print、MI::print
c、d、e:
void foo(double cval)
	{
		int dval;
		dval = Base1::dval + Derived::dval;//c
		Base2::fval = dvec.back();//d
		Derived::sval[0] = Base1::cval;//e
	}

18.28
struct Base {
	void bar(int);//需要限定符
protected:
	int ival;
};
struct Derived1 :public virtual Base {
	void bar(char);//可直接访问,覆盖基类的bar
	void foo(char);//需要限定符,否则不明确
protected:
	char cval;//需要限定符,否则不明确
};
struct Derived2 :public virtual Base {
	void foo(int);//需要限定符,否则不明确
protected:
	int ival;//可直接访问,覆盖基类的ival
	char cval;//需要限定符,否则不明确
};
struct VMI :public Derived1, public Derived2 {
	void func() {
		bar(4);//Derived1
		Base::bar(4);//Base
		Derived1::foo('a');//Derived1
		Derived2::foo(4);//Derived2
		auto t1 = ival;//Derived2
		t1 = Base::ival;//Base
		auto t2 = Derived1::cval;
		t2 = Derived2::cval;
	}
};

18.29
a、
Class
Base
D1
D2
MI
Class(与Base中的class不相同,独立,也就是说Final继承两个Class)
b、与构造顺序相反:Class(最外层的)->MI->D2-D1->Base->Class(Base的基类)
c、
(a)、错误,Class是Base的基类,而pb是Base类
(b)、正确,基类Class可以指向所有子类
(c)、错误、pb是Base类,MI是Base的子类
(d)、正确、D2是MI的基类

18.30
class Class {};
class Base :public Class {

protected:
	int ival;
public:
	Base() :ival(0),Class() {};
	Base(const Base &b) = default;
	Base(int a) :ival(a),Class() {}
};
class D1 :public virtual Base {
public:
	D1() :Base() {}
	D1(const D1 &b) = default;
	D1(int a) :Base(a) {}
};
class D2 :public virtual Base {
public:
	D2() :Base() {}
	D2(const D2 &b) = default;
	D2(int a) :Base(a) {}
};
class MI :public D1, public D2 {
public:
	MI() {}
	MI(const MI &m) :Base(m), D1(m), D2(m) {}
	MI(int i) :Base(i), D1(i), D2(i) {}
};
class Final :public MI, public Class {
public:
	Final() {}
	Final(const Final &f) : Base(f), MI(f), Class() {}
	Final(int i) : Base(i), Class() {}
};













2016年4月25日02:31:04

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值