c++ primer中文版第五版作业第十八章

2024-03-08 23:04

本文主要是介绍c++ primer中文版第五版作业第十八章,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

仓库地址

文章目录

      • 18.1
      • 18.2
      • 18.3
      • 18.4
      • 18.5
      • 18.6
      • 18.7
      • 18.8
      • 18.9
      • 18.10
      • 18.11
      • 18.12
      • 18.13
      • 18.14
      • 18.15
      • 18.16
        • 位置一
          • using声明
        • 位置二
          • using声明
        • 位置一
          • using指示
        • 位置二
          • using指示
      • 18.17
      • 18.18
      • 18.19
      • 18.20
      • 18.21
      • 18.22
      • 18.23
      • 18.24
      • 18.25
      • 18.26
      • 18.26
      • 18.28
      • 18.29
      • 18.30

18.1

  1. 此时r是一个range_error类型的局部对象
  2. 此时p是exception类型的指针,指向局部对象r
    如果throw p就会抛出一个指向局部对象的指针,那么有可能在执行catch语句之前,该局部对象已经被销毁。

18.2

 v和in可以调用其析构函数释放资源,而p无法正确释放资源,导致内存泄漏。

18.3

  1. 使用智能指针管理p
    unique_ptr<int []> p(new int[v.size()])
  2. 使用类来控制资源的分配
class ptr
{public:explicit ptr(size_t len):p(new int[len]) {}ptr(const ptr&)=delete;ptr & operator=(const ptr&)=delete;~ptr(){delete [] p;}private:int *p;
};

18.4

catch语句是按照其出现的顺序逐一进行匹配的,所以根据继承体系catch(exception)后面的catch子句永远无法被匹配到。

try{
//
}catch(overflow_error eobj){
//
}catch(const runtime_error &re){
//
}catch(exception){/**/}

18.5

#include <iostream>
#include <exception>
#include <stdexcept>
#include <cstdlib>
int main(){try{//使用c++标准库
}catch(const exception &e){std::cout<<e.what()<<std::endl;abort();
}
}

18.6

  1. throw exceptionType * eobj,注意不能抛出一个指向局部对象的指针
  2. 抛出的所有异常都能被捕获
  3. int a=1;throw a;抛出的所有int类型值都能被捕获,但是其余的整型类型无法进行算数类型转换为int。

18.7

#ifndef BLOB_H
#define BLOB_H
#include <iostream>
#include <string>
#include <memory>
#include <vector>
#include <string>
#include <initializer_list>
#include <stdexcept>
template <typename> class BlobPtr;
template <typename> class Blob;
//Blob
template <typename T> bool operator==(const Blob<T> &,const Blob<T> &);
template <typename T> bool operator!=(const Blob<T> &,const Blob<T> &);
template <typename T> bool operator<(const Blob<T> &,const Blob<T> &);
template <typename T> bool operator<=(const Blob<T> &,const Blob<T> &);
template <typename T> bool operator>(const Blob<T> &,const Blob<T> &);
template <typename T> bool operator>=(const Blob<T> &,const Blob<T> &);
template <typename T> class Blob
{friend class BlobPtr<T>;friend bool operator==<T>(const Blob<T> &,const Blob<T> &);friend bool operator!=<T>(const Blob<T> &,const Blob<T> &);friend bool operator< <T>(const Blob<T> &,const Blob<T> &);friend bool operator<= <T>(const Blob<T> &,const Blob<T> &);friend bool operator> <T>(const Blob<T> &,const Blob<T> &);friend bool operator>= <T>(const Blob<T> &,const Blob<T> &);public:typedef T value_type;typedef typename std::vector<T>::size_type size_type;Blob() try:data(std::make_shared<std::vector<T>>()){} catch(std::bad_alloc &e){std::cout<<e.what()<<std::endl;}Blob(std::initializer_list<T> il) try:data(std::make_shared<std::vector<T>>(il)){} catch(std::bad_alloc &e){std::cout<<e.what()<<std::endl;}Blob(const Blob &org) try:data(std::make_shared<std::vector<T>>(*org.data)){} catch(std::bad_alloc &e){std::cout<<e.what()<<std::endl;}template <typename it> Blob(it b,it e) try:data(std::make_shared<std::vector<T>>(b,e)) {} catch(std::bad_alloc &ba){std::cout<<ba.what()<<std::endl;}Blob &operator=(const Blob &);T & operator[](size_type i);const T & operator[](size_type i) const;size_type size() const {return data->size();}bool empty() const {return data->empty;}void push_back(const T &t){data->push_back(t);}void push_back(T &&t){data->push_back(std::move(t));}void pop_back();T & front();T & back();const T & front() const;const T & back() const;BlobPtr<T> begin();BlobPtr<T> end();private:std::shared_ptr<std::vector<T>> data;void check(size_type i,const std::string &msg) const;
};
//BlobPtr
template <typename T> bool operator==(const BlobPtr<T> &,const BlobPtr<T> &);
template <typename T> bool operator!=(const BlobPtr<T> &,const BlobPtr<T> &);
template <typename T> bool operator<(const BlobPtr<T> &,const BlobPtr<T> &);
template <typename T> bool operator<=(const BlobPtr<T> &,const BlobPtr<T> &);
template <typename T> bool operator>(const BlobPtr<T> &,const BlobPtr<T> &);
template <typename T> bool operator>=(const BlobPtr<T> &,const BlobPtr<T> &);
template <typename T> class BlobPtr
{friend bool operator==<T>(const BlobPtr<T> &,const BlobPtr<T> &);friend bool operator!=<T>(const BlobPtr<T> &,const BlobPtr<T> &);friend bool operator< <T>(const BlobPtr<T> &,const BlobPtr<T> &);friend bool operator<=<T>(const BlobPtr<T> &,const BlobPtr<T> &);friend bool operator><T>(const BlobPtr<T> &,const BlobPtr<T> &);friend bool operator>=<T>(const BlobPtr<T> &,const BlobPtr<T> &);public:typedef typename std::vector<T>::size_type size_type;BlobPtr():curr(0){}BlobPtr(const Blob<T> &blob,size_type sz=0):wptr(blob.data),curr(sz){}T & operator[](size_type i);const T & operator[](size_type i) const;BlobPtr & operator++();BlobPtr & operator++(int);BlobPtr & operator--();BlobPtr & operator--(int);BlobPtr operator+(size_type) const;BlobPtr operator-(size_type) const;BlobPtr operator+=(size_type) const;BlobPtr operator-=(size_type) const;T & operator*() const;T * operator->() const;private:std::shared_ptr<std::vector<T>> check(size_type i,const std::string &msg) const;std::weak_ptr<std::vector<T>> wptr;size_type curr=0;
};
//Blob
template <typename T> Blob<T> & Blob<T>::operator=(const Blob &rhs)
{data=std::make_shared<std::vector<T>>(*rhs.data);return *this;
}
template <typename T> T & Blob<T>::operator[](size_type i)
{check(i,"subscript out of range");return (*data)[i];
}
template <typename T> const T & Blob<T>::operator[](size_type i) const
{check(i,"subscript out of range");return (*data)[i];
}
template <typename T> void Blob<T>::pop_back()
{check(0,"pop_back on empty Blob");data->pop_back();
}
template <typename T> T & Blob<T>::front()
{check(0,"front on empty Blob");return data->front();
}
template <typename T> const T & Blob<T>::front() const
{check(0,"front on empty Blob");return data->front();
}
template <typename T> T & Blob<T>::back()
{check(0,"back on empty Blob");return data->back();
}
template <typename T> const T & Blob<T>::back() const
{check(0,"back on empty Blob");return data->back();
}
template <typename T> BlobPtr<T> Blob<T>::begin()
{return BlobPtr<T>(*this);
}
template <typename T> BlobPtr<T> Blob<T>::end()
{return BlobPtr<T>(*this,data->size());
}
template <typename T> inline void Blob<T>::check(size_type i,const std::string &msg) const
{if(i>=data->size())throw std::out_of_range(msg);
}
template <typename T> bool operator==(const Blob<T> &lhs,const Blob<T> &rhs)
{return *lhs.data==*rhs.data;
}
template <typename T> bool operator!=(const Blob<T> &lhs,const Blob<T> &rhs)
{return !(lhs==rhs);
}
template <typename T> bool operator<(const Blob<T> &lhs,const Blob<T> &rhs)
{return *lhs.data<*rhs.data;
}
template <typename T> bool operator<=(const Blob<T> &lhs,const Blob<T> &rhs)
{return !(lhs>rhs);
}
template <typename T> bool operator>(const Blob<T> &lhs,const Blob<T> &rhs)
{return *lhs.data>*rhs.data;
}
template <typename T> bool operator>=(const Blob<T> &lhs,const Blob<T> &rhs)
{return !(lhs<rhs);
}
//BlobPtr
template <typename T> std::shared_ptr<std::vector<T>> BlobPtr<T>::check(size_type i,const std::string &msg) const
{auto ret=wptr.lock();if(!ret)throw std::runtime_error("unbound BlobPtr");if(i>=ret->size())throw std::out_of_range(msg);return ret;
}
template <typename T> T & BlobPtr<T>::operator[](size_type i)
{auto ret=check(i,"index out of range");return (*ret)[i];
}
template <typename T> const T & BlobPtr<T>::operator[](size_type i) const
{auto ret=check(i,"index out of range");return (*ret)[i];
}
template <typename T> BlobPtr<T> & BlobPtr<T>::operator++()
{check(curr,"increment past end of BlobPtr");++curr;return *this;
}
template <typename T> BlobPtr<T> & BlobPtr<T>::operator++(int)
{BlobPtr ret=*this;++*this;return ret;
}
template <typename T> BlobPtr<T> & BlobPtr<T>::operator--()
{--curr;check(curr,"decrement past the begin of BlobPtr");return *this;
}
template <typename T> BlobPtr<T> & BlobPtr<T>::operator--(int)
{BlobPtr ret=*this;--*this;return ret;
}
template <typename T> BlobPtr<T> BlobPtr<T>::operator+(size_type i) const
{BlobPtr ret(*this);ret+=i;return ret;
}
template <typename T> BlobPtr<T> BlobPtr<T>::operator-(size_type i) const
{BlobPtr ret(*this);ret-=i;return ret;
}
template <typename T> BlobPtr<T> BlobPtr<T>::operator+=(size_type i) const
{check(curr+i,"increment past end of range");while(--i)++*this;return *this;
}
template <typename T> BlobPtr<T> BlobPtr<T>::operator-=(size_type i) const
{check(curr-i,"decrement past begin of range");while(--i)--*this;return *this;
}
template <typename T> T & BlobPtr<T>::operator*() const
{auto p=check(curr,"dereference past end");return (*p)[curr];
}
template <typename T> T * BlobPtr<T>::operator->() const
{return & this->operator*();
}
template <typename T> bool operator==(const BlobPtr<T> &lhs,const BlobPtr<T> &rhs)
{auto l=lhs.wptr.lock();auto r=rhs.wptr.lock();if(l==r)return (!r||lhs.curr==rhs.curr);elsereturn false;
}
template <typename T> bool operator!=(const BlobPtr<T> &lhs,const BlobPtr<T> &rhs)
{return !(lhs==rhs);
}
template <typename T> bool operator<(const BlobPtr<T> &lhs,const BlobPtr<T> &rhs)
{auto l=lhs.wptr.lock();auto r=rhs.wptr.lock();if(l==r&&l)return lhs.curr<rhs.curr;elsereturn false;
}
template <typename T> bool operator<=(const BlobPtr<T> &lhs,const BlobPtr<T> &rhs)
{return !(lhs>rhs);
}
template <typename T> bool operator>(const BlobPtr<T> &lhs,const BlobPtr<T> &rhs)
{return rhs<lhs;
}
template <typename T> bool operator>=(const BlobPtr<T> &lhs,const BlobPtr<T> &rhs)
{return !(lhs<rhs);
}
#endif

18.8

#ifndef BLOB_H
#define BLOB_H
#include <iostream>
#include <string>
#include <memory>
#include <vector>
#include <string>
#include <initializer_list>
#include <stdexcept>
template <typename> class BlobPtr;
template <typename> class Blob;
//Blob
template <typename T> bool operator==(const Blob<T> &,const Blob<T> &);
template <typename T> bool operator!=(const Blob<T> &,const Blob<T> &);
template <typename T> bool operator<(const Blob<T> &,const Blob<T> &);
template <typename T> bool operator<=(const Blob<T> &,const Blob<T> &);
template <typename T> bool operator>(const Blob<T> &,const Blob<T> &);
template <typename T> bool operator>=(const Blob<T> &,const Blob<T> &);
template <typename T> class Blob
{friend class BlobPtr<T>;friend bool operator==<T>(const Blob<T> &,const Blob<T> &);friend bool operator!=<T>(const Blob<T> &,const Blob<T> &);friend bool operator< <T>(const Blob<T> &,const Blob<T> &);friend bool operator<= <T>(const Blob<T> &,const Blob<T> &);friend bool operator> <T>(const Blob<T> &,const Blob<T> &);friend bool operator>= <T>(const Blob<T> &,const Blob<T> &);public:typedef T value_type;typedef typename std::vector<T>::size_type size_type;Blob() noexcept(false) try:data(std::make_shared<std::vector<T>>()){} catch(std::bad_alloc &e){std::cout<<e.what()<<std::endl;}Blob(std::initializer_list<T> il) noexcept(false) try:data(std::make_shared<std::vector<T>>(il)){} catch(std::bad_alloc &e){std::cout<<e.what()<<std::endl;}Blob(const Blob &org) noexcept(false) try:data(std::make_shared<std::vector<T>>(*org.data)){} catch(std::bad_alloc &e){std::cout<<e.what()<<std::endl;}template <typename it> Blob(it b,it e) noexcept(false) try:data(std::make_shared<std::vector<T>>(b,e)) {} catch(std::bad_alloc &ba){std::cout<<ba.what()<<std::endl;}Blob &operator=(const Blob &);T & operator[](size_type i);const T & operator[](size_type i) const;size_type size() const {return data->size();}bool empty() const {return data->empty;}void push_back(const T &t){data->push_back(t);}void push_back(T &&t){data->push_back(std::move(t));}void pop_back();T & front();T & back();const T & front() const;const T & back() const;BlobPtr<T> begin();BlobPtr<T> end();~Blob() noexcept {};private:std::shared_ptr<std::vector<T>> data;void check(size_type i,const std::string &msg) const;
};
//BlobPtr
template <typename T> bool operator==(const BlobPtr<T> &,const BlobPtr<T> &);
template <typename T> bool operator!=(const BlobPtr<T> &,const BlobPtr<T> &);
template <typename T> bool operator<(const BlobPtr<T> &,const BlobPtr<T> &);
template <typename T> bool operator<=(const BlobPtr<T> &,const BlobPtr<T> &);
template <typename T> bool operator>(const BlobPtr<T> &,const BlobPtr<T> &);
template <typename T> bool operator>=(const BlobPtr<T> &,const BlobPtr<T> &);
template <typename T> class BlobPtr
{friend bool operator==<T>(const BlobPtr<T> &,const BlobPtr<T> &);friend bool operator!=<T>(const BlobPtr<T> &,const BlobPtr<T> &);friend bool operator< <T>(const BlobPtr<T> &,const BlobPtr<T> &);friend bool operator<=<T>(const BlobPtr<T> &,const BlobPtr<T> &);friend bool operator><T>(const BlobPtr<T> &,const BlobPtr<T> &);friend bool operator>=<T>(const BlobPtr<T> &,const BlobPtr<T> &);public:typedef typename std::vector<T>::size_type size_type;BlobPtr():curr(0){}BlobPtr(const Blob<T> &blob,size_type sz=0):wptr(blob.data),curr(sz){}T & operator[](size_type i);const T & operator[](size_type i) const;BlobPtr & operator++();BlobPtr & operator++(int);BlobPtr & operator--();BlobPtr & operator--(int);BlobPtr operator+(size_type) const;BlobPtr operator-(size_type) const;BlobPtr operator+=(size_type) const;BlobPtr operator-=(size_type) const;T & operator*() const;T * operator->() const;private:std::shared_ptr<std::vector<T>> check(size_type i,const std::string &msg) const;std::weak_ptr<std::vector<T>> wptr;size_type curr=0;
};
//Blob
template <typename T> Blob<T> & Blob<T>::operator=(const Blob &rhs)
{data=std::make_shared<std::vector<T>>(*rhs.data);return *this;
}
template <typename T> T & Blob<T>::operator[](size_type i)
{check(i,"subscript out of range");return (*data)[i];
}
template <typename T> const T & Blob<T>::operator[](size_type i) const
{check(i,"subscript out of range");return (*data)[i];
}
template <typename T> void Blob<T>::pop_back()
{check(0,"pop_back on empty Blob");data->pop_back();
}
template <typename T> T & Blob<T>::front()
{check(0,"front on empty Blob");return data->front();
}
template <typename T> const T & Blob<T>::front() const
{check(0,"front on empty Blob");return data->front();
}
template <typename T> T & Blob<T>::back()
{check(0,"back on empty Blob");return data->back();
}
template <typename T> const T & Blob<T>::back() const
{check(0,"back on empty Blob");return data->back();
}
template <typename T> BlobPtr<T> Blob<T>::begin()
{return BlobPtr<T>(*this);
}
template <typename T> BlobPtr<T> Blob<T>::end()
{return BlobPtr<T>(*this,data->size());
}
template <typename T> inline void Blob<T>::check(size_type i,const std::string &msg) const
{if(i>=data->size())throw std::out_of_range(msg);
}
template <typename T> bool operator==(const Blob<T> &lhs,const Blob<T> &rhs)
{return *lhs.data==*rhs.data;
}
template <typename T> bool operator!=(const Blob<T> &lhs,const Blob<T> &rhs)
{return !(lhs==rhs);
}
template <typename T> bool operator<(const Blob<T> &lhs,const Blob<T> &rhs)
{return *lhs.data<*rhs.data;
}
template <typename T> bool operator<=(const Blob<T> &lhs,const Blob<T> &rhs)
{return !(lhs>rhs);
}
template <typename T> bool operator>(const Blob<T> &lhs,const Blob<T> &rhs)
{return *lhs.data>*rhs.data;
}
template <typename T> bool operator>=(const Blob<T> &lhs,const Blob<T> &rhs)
{return !(lhs<rhs);
}
//BlobPtr
template <typename T> std::shared_ptr<std::vector<T>> BlobPtr<T>::check(size_type i,const std::string &msg) const
{auto ret=wptr.lock();if(!ret)throw std::runtime_error("unbound BlobPtr");if(i>=ret->size())throw std::out_of_range(msg);return ret;
}
template <typename T> T & BlobPtr<T>::operator[](size_type i)
{auto ret=check(i,"index out of range");return (*ret)[i];
}
template <typename T> const T & BlobPtr<T>::operator[](size_type i) const
{auto ret=check(i,"index out of range");return (*ret)[i];
}
template <typename T> BlobPtr<T> & BlobPtr<T>::operator++()
{check(curr,"increment past end of BlobPtr");++curr;return *this;
}
template <typename T> BlobPtr<T> & BlobPtr<T>::operator++(int)
{BlobPtr ret=*this;++*this;return ret;
}
template <typename T> BlobPtr<T> & BlobPtr<T>::operator--()
{--curr;check(curr,"decrement past the begin of BlobPtr");return *this;
}
template <typename T> BlobPtr<T> & BlobPtr<T>::operator--(int)
{BlobPtr ret=*this;--*this;return ret;
}
template <typename T> BlobPtr<T> BlobPtr<T>::operator+(size_type i) const
{BlobPtr ret(*this);ret+=i;return ret;
}
template <typename T> BlobPtr<T> BlobPtr<T>::operator-(size_type i) const
{BlobPtr ret(*this);ret-=i;return ret;
}
template <typename T> BlobPtr<T> BlobPtr<T>::operator+=(size_type i) const
{check(curr+i,"increment past end of range");while(--i)++*this;return *this;
}
template <typename T> BlobPtr<T> BlobPtr<T>::operator-=(size_type i) const
{check(curr-i,"decrement past begin of range");while(--i)--*this;return *this;
}
template <typename T> T & BlobPtr<T>::operator*() const
{auto p=check(curr,"dereference past end");return (*p)[curr];
}
template <typename T> T * BlobPtr<T>::operator->() const
{return & this->operator*();
}
template <typename T> bool operator==(const BlobPtr<T> &lhs,const BlobPtr<T> &rhs)
{auto l=lhs.wptr.lock();auto r=rhs.wptr.lock();if(l==r)return (!r||lhs.curr==rhs.curr);elsereturn false;
}
template <typename T> bool operator!=(const BlobPtr<T> &lhs,const BlobPtr<T> &rhs)
{return !(lhs==rhs);
}
template <typename T> bool operator<(const BlobPtr<T> &lhs,const BlobPtr<T> &rhs)
{auto l=lhs.wptr.lock();auto r=rhs.wptr.lock();if(l==r&&l)return lhs.curr<rhs.curr;elsereturn false;
}
template <typename T> bool operator<=(const BlobPtr<T> &lhs,const BlobPtr<T> &rhs)
{return !(lhs>rhs);
}
template <typename T> bool operator>(const BlobPtr<T> &lhs,const BlobPtr<T> &rhs)
{return rhs<lhs;
}
template <typename T> bool operator>=(const BlobPtr<T> &lhs,const BlobPtr<T> &rhs)
{return !(lhs<rhs);
}
#endif

18.9

Sales_data.h

#include <iostream>
#include <string>
#include <stdexcept>
class isbn_mismatch: public std::logic_error
{
public:explicit isbn_mismatch(const std::string &s):std::logic_error(s) {}isbn_mismatch(const std::string &s,const std::string &lhs,const std::string &rhs):std::logic_error(s),left(lhs),right(rhs) {}const std::string left,right;
};
class Sales_data
{friend std::istream & operator>>(std::istream &,Sales_data &);friend std::ostream & operator<<(std::ostream &,const Sales_data &);friend Sales_data operator+(const Sales_data &,const Sales_data &);public:std::string isbn() const {return bookNo;}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 & operator+=(const Sales_data &);operator std::string() const {return bookNo;}operator double() const {return revenue;}private:std::string bookNo;unsigned units_sold=0;double revenue=0.0;double avg_price() const;
};
std::istream & operator>>(std::istream &,Sales_data &);
std::ostream & operator<<(std::ostream &,const Sales_data &);
Sales_data operator+(const Sales_data &,const Sales_data &);
bool compareIsbn(const Sales_data &lhs,const Sales_data &rhs);

Sales_data.cpp

#include "Sales_data.h"
inline double Sales_data::avg_price() const
{if(units_sold)return revenue/units_sold;elsereturn 0;
}
std::istream & operator>>(std::istream &is,Sales_data &src)
{double price=0.0;is>>src.bookNo>>src.units_sold>>price;if(is)src.revenue=src.units_sold*price;elsesrc=Sales_data();return is;
}
std::ostream & operator<<(std::ostream &os,const Sales_data &src)
{os<<src.isbn()<<" "<<src.units_sold<<" "<<src.revenue<<" "<<src.avg_price();return os;
}
Sales_data & Sales_data::operator+=(const Sales_data & rhs)
{*this=*(this)+rhs;return *this;
}
Sales_data operator+(const Sales_data &lhs,const Sales_data &rhs)
{Sales_data tmp;if(lhs.isbn()!=rhs.isbn())throw isbn_mismatch("wrong isbns!",lhs.isbn(),rhs.isbn());tmp.bookNo=lhs.bookNo;tmp.units_sold=lhs.units_sold+rhs.units_sold;tmp.revenue=lhs.revenue+rhs.revenue;return tmp;
}
bool compareIsbn(const Sales_data &lhs,const Sales_data &rhs)
{return lhs.isbn()<rhs.isbn();
}

test1.cpp

#include <iostream>
#include "Sales_data.h"
int main(void)
{Sales_data a("111",2,30),b("112",3,50);a+b;return  0;
}

不处理异常的输出
terminate called after throwing an instance of ‘isbn_mismatch’
what(): wrong isbns!
Aborted
test2.cpp

#include <iostream>
#include "Sales_data.h"
int main(void)
{Sales_data a("111",2,30),b("112",3,50);try{a+b;}catch(const isbn_mismatch &e){std::cerr<<e.what()<<": left isbn ("<<e.left<<") right isbn ("<<e.right<<")"<<std::endl;}return  0;
}

处理异常的输出
wrong isbns!: left isbn (111) right isbn (112)

18.10

见18.9

18.11

 如果what函数抛出异常的话,没有对应的catch子句捕获处理,就会调用terminate使程序结束,破坏正常逻辑。

18.12

Query.h

#ifndef _QUERY_H
#define _QUERY_H
#include <iostream>
#include <string>
#include <vector>
#include <map>
#include <set>
#include <memory>
#include <fstream>
namespace chapter15
{class QueryResult;class TextQuery{public:using line_no=std::vector<std::string>::size_type;TextQuery(std::ifstream &);QueryResult query(const std::string &) const;private:std::shared_ptr<std::vector<std::string>> file;std::map<std::string,std::shared_ptr<std::set<line_no>>> wm;};class QueryResult{friend std::ostream &print(std::ostream &,const QueryResult &);public:QueryResult(std::string s,std::shared_ptr<std::set<std::vector<std::string>::size_type>> l,std::shared_ptr<std::vector<std::string>> f):sought(s),lines(l),file(f){}std::set<std::vector<std::string>::size_type>::iterator begin() const {return lines->begin();}std::set<std::vector<std::string>::size_type>::iterator end() const {return lines->end();}std::shared_ptr<std::vector<std::string>> get_file(){return file;}private:std::string sought;std::shared_ptr<std::set<std::vector<std::string>::size_type>> lines;std::shared_ptr<std::vector<std::string>> file;};std::ostream &print(std::ostream &,const QueryResult &);inline std::string make_plural(std::size_t count,const std::string &word,const std::string &ending){return (count>1)?word+ending:word;}class Query_base{friend class Query;protected:using line_no=TextQuery::line_no;virtual ~Query_base()=default;private:virtual QueryResult eval(const TextQuery &) const=0;virtual std::string rep() const=0;};class Query{friend Query operator~(const Query &);friend Query operator&(const Query &,const Query &);friend Query operator|(const Query &,const Query &);public:Query(const std::string &);QueryResult eval(const TextQuery &t) const {return q->eval(t);}std::string rep() const {return q->rep();}private:Query(std::shared_ptr<Query_base> query):q(query) {}std::shared_ptr<Query_base> q;};class WordQuery:public Query_base{friend class Query;private:WordQuery(const std::string &s):query_word(s) {}virtual QueryResult eval(const TextQuery &t) const {return t.query(query_word);}virtual std::string rep() const {return query_word;}std::string query_word;};inline Query::Query(const std::string &s):q(new WordQuery(s)) {}class NotQuery:public Query_base{friend Query operator~(const Query &);private:NotQuery(const Query &q):query(q) {}virtual QueryResult eval(const TextQuery &) const;virtual std::string rep() const {return "~("+query.rep()+")";}Query query;};inline Query operator~(const Query &q) {return std::shared_ptr<Query_base>(new NotQuery(q));}class BinaryQuery:public Query_base{protected:BinaryQuery(const Query &left,const Query &right,const std::string &s):lhs(left),rhs(right),opSym(s) {}virtual std::string rep() const {return "("+lhs.rep()+" "+opSym+" "+rhs.rep()+")";}Query lhs,rhs;std::string opSym;};class AndQuery:public BinaryQuery{friend Query operator&(const Query&,const Query&);private:AndQuery(const Query &left,const Query &right):BinaryQuery(left,right,"&") {}virtual QueryResult eval(const TextQuery &) const;};inline Query operator&(const Query &left,const Query &right) {return std::shared_ptr<Query_base>(new AndQuery(left,right));}class OrQuery:public BinaryQuery{friend Query operator|(const Query &,const Query &);private:OrQuery(const Query &left,const Query &right):BinaryQuery(left,right,"|") {}virtual QueryResult eval(const TextQuery &) const;};inline Query operator|(const Query &left,const Query &right) {return std::shared_ptr<Query_base>(new OrQuery(left,right));}inline std::ostream & operator<<(std::ostream &os,const Query &q) {return os<<q.rep();}
}
#endif

Query.cpp

#include <sstream>
#include <algorithm>
#include <cctype>
#include "Query.h"
namespace chapter15
{TextQuery::TextQuery(std::ifstream &infile):file(new std::vector<std::string>){std::string text;while(getline(infile,text)){file->push_back(text);std::size_t line_number=file->size()-1;std::istringstream line(text);std::string word;while(line>>word){std::string key_word;for(auto c:word){if(!ispunct(c))key_word+=c;}std::shared_ptr<std::set<line_no>> &lines=wm[key_word];if(!lines)lines.reset(new std::set<line_no>);lines->insert(line_number);}}}QueryResult TextQuery::query(const std::string &sought) const{static std::shared_ptr<std::set<line_no>> nodata(new std::set<line_no>);std::map<std::string,std::shared_ptr<std::set<line_no>>>::const_iterator map_it=wm.find(sought);if(map_it==wm.end())return QueryResult(sought,nodata,file);elsereturn QueryResult(sought,map_it->second,file);}std::ostream &print(std::ostream &os,const QueryResult &qr){os<<"Executing Query for: "<<qr.sought<<std::endl;os<<qr.sought<<" occurs "<<qr.lines->size()<<" "<<make_plural(qr.lines->size(),"time","s")<<std::endl;for(auto num:*(qr.lines))os<<"\t(line "<<num+1<<") "<<*(qr.file->begin()+num)<<std::endl;return os;}QueryResult NotQuery::eval(const TextQuery &text) const{auto result=query.eval(text);auto beg=result.begin(),end=result.end();auto ret_lines=std::make_shared<std::set<line_no>>();auto sz=result.get_file()->size();for(std::size_t n=0;n!=sz;++n){if(beg==end||*beg!=n)ret_lines->insert(n);else if(beg!=end)++beg;}return QueryResult(rep(),ret_lines,result.get_file());}QueryResult OrQuery::eval(const TextQuery &text) const{auto left=lhs.eval(text),right=rhs.eval(text);auto ret_lines=std::make_shared<std::set<line_no>>(left.begin(),left.end());ret_lines->insert(right.begin(),right.end());return QueryResult(rep(),ret_lines,left.get_file());}QueryResult AndQuery::eval(const TextQuery &text) const{auto left=lhs.eval(text),right=rhs.eval(text);auto ret_lines=std::make_shared<std::set<line_no>>();set_intersection(left.begin(),left.end(),right.begin(),right.end(),inserter(*ret_lines,ret_lines->begin()));return QueryResult(rep(),ret_lines,left.get_file());}
}

TextQuery.h

#ifndef TEXT_QUERY_H
#define TEXT_QUERY_H
#include <iostream>
#include <string>
#include <vector>
#include <map>
#include <set>
#include <memory>
#include <fstream>
#include <tuple>
namespace chapter10
{class TextQuery{public:using line_no=std::vector<std::string>::size_type;TextQuery(std::ifstream &);std::tuple<std::string,std::shared_ptr<std::set<std::vector<std::string>::size_type>>,std::shared_ptr<std::vector<std::string>>> query(const std::string &) const;private:std::shared_ptr<std::vector<std::string>> file;std::map<std::string,std::shared_ptr<std::set<line_no>>> wm;};inline std::string make_plural(std::size_t count,const std::string &word,const std::string &ending){return (count>1)?word+ending:word;}std::ostream &print(std::ostream &,const std::tuple<std::string,std::shared_ptr<std::set<std::vector<std::string>::size_type>>,std::shared_ptr<std::vector<std::string>>> &);
}
#endif

TextQuery.cpp

#include <fstream>
#include <iostream>
#include <sstream>
#include <vector>
#include <set>
#include <string>
#include <memory>
#include "TextQuery.h"
using namespace std;
namespace chapter10
{TextQuery::TextQuery(ifstream &infile):file(new vector<string>){string text;while(getline(infile,text)){file->push_back(text);size_t line_number=file->size()-1;istringstream line(text);string word;while(line>>word){shared_ptr<set<line_no>> &lines=wm[word];if(!lines)lines.reset(new set<line_no>);lines->insert(line_number);}}}std::tuple<std::string,std::shared_ptr<std::set<std::vector<std::string>::size_type>>,std::shared_ptr<std::vector<std::string>>> TextQuery::query(const string &sought) const{static shared_ptr<set<line_no>> nodata(new set<line_no>);map<string,shared_ptr<set<line_no>>>::const_iterator map_it=wm.find(sought);if(map_it==wm.end())return tuple(sought,nodata,file);elsereturn tuple(sought,map_it->second,file);}std::ostream &print(std::ostream &os,const std::tuple<std::string,std::shared_ptr<std::set<std::vector<std::string>::size_type>>,std::shared_ptr<std::vector<std::string>>> &tp){os<<std::get<0>(tp)<<" occurs "<<std::get<1>(tp)->size()<<" "<<make_plural(std::get<1>(tp)->size(),"time","s")<<std::endl;for(auto num:*(get<1>(tp)))os<<"\t(line "<<num+1<<")"<<*(get<2>(tp)->begin()+num)<<std::endl;return os;}
}

test.cpp

#include <fstream>
#include "Query.h"
using namespace std;
using chapter15::Query;
using chapter15::TextQuery;
int main(int argc,char *argv[])
{ifstream infile(argv[1]);TextQuery text(infile);Query q=Query("fiery")&Query("bird")|Query("wind");print(cout,q.eval(text));return 0;
}

18.13

 需要使用文件作用域或者命名空间作用域的静态变量时可以使用未命名的命名空间。

18.14

mathLib::MatrixLib::matrix mathLib::MatrixLib::operator*(const matrix &,const matrix &);

18.15

using声明:一次只引入命名空间的一个成员,它的有效范围从using声明的地方开始,到using声音所在作用域结束为止。
using指示:使特定的命名空间中所有的名字都可见,这些名字一般被看作是出现在最近的外层作用域中,如果遇到成员冲突的情况,需要使用作用域运算符指明所需的版本。

18.16

位置一
using声明

ivar成员冲突

位置二
using声明

dvar成员冲突

位置一
using指示

++ivar这句将有二义性错误

位置二
using指示

++ivar这句将有二义性错误

18.17

1

#include <iostream>	
namespace Exercise
{int ivar=0;double dvar=0;const int limit=1000;
}
int ivar=0;using Exercise::ivar;
using Exercise::dvar;
using Exercise::limit;void manip()
{double dvar=3.1416;int iobj=limit+1;++ivar;++::ivar;
}
int main(void)
{return 0;
}

2

#include <iostream>	
namespace Exercise
{int ivar=0;double dvar=0;const int limit=1000;
}
int ivar=0;void manip()
{using Exercise::ivar;
using Exercise::dvar;
using Exercise::limit;double dvar=3.1416;int iobj=limit+1;++ivar;++::ivar;
}
int main(void)
{return 0;
}

3

#include <iostream>	
namespace Exercise
{int ivar=0;double dvar=0;const int limit=1000;
}
int ivar=0;using namespace Exercise;void manip()
{double dvar=3.1416;int iobj=limit+1;++ivar;++::ivar;
}
int main(void)
{return 0;
}

4

#include <iostream>	
namespace Exercise
{int ivar=0;double dvar=0;const int limit=1000;
}
int ivar=0;void manip()
{using namespace Exercise;double dvar=3.1416;int iobj=limit+1;++ivar;++::ivar;
}
int main(void)
{return 0;
}

18.18

 当mem1是一个string时程序因为更特例化的原因,会调用string中定义的swap版本,而int是内置类型,内置类型没有特定版本的swap,所以会调用std::swap。

18.19

 如果使用std::swap的形式,则是直接指明调用std命名空间中的swap版本。

18.20

  • 命名空间primerLib中声明的compte将被加入候选函数集
    候选函数void compute() void compute(const void *) void compute(int) void compute(double,double=3.4) void compute(char*,char*=0)
    可行函数
    void compute(const void *)0能转换成任意指针类型
    void compute(int)精确匹配
    void compute(double,double=3.4)int向double的算术类型转换
    void compute(char*,char*=0)0能转换成任意指针类型
  • 如果将using声明置于f函数中compute的调用点之前,将隐藏全局作用域中声明的compute.
    候选函数void compute() void compute(const void *)
    可行函数
    void compute(const void *)0能转换成任意指针类型

18.21

1 正确,public继承CAD,private继承Vehicle
2 错误,在一个派生列表中重复继承了同一个基类
3 正确,public继承istream,public继承ostream

18.22

 构造函数的执行顺序是A->B->C->X->Y->Z->MI

18.23

都允许

18.24

ZooAnimal *pz=new Panda("ying_yang")
pb->print();//调用Panda::print()
pb->cuddle();//错误,不属于ZooAnimal的接口
pb->highlight();//错误,不属于ZooAnimal的接口
delete->pb;//正确,Panda::~Panda()

18.25

  1. MI::print()
  2. MI::print()
  3. MI::print()
  4. MI::~MI()
  5. MI::~MI()
  6. MI::~MI()

18.26

 因为派生类的名字将隐藏基类的同名成员,所以MI不加前缀限定符的print函数只有接受std::vector参数的版本,而42无法隐式转换为该类型,所以调用失败。
可以这样修改:

struct MI:public Derived,public Base2
{void print(std::vector<double>);void print(int i){Base1::print(i);}protected:int *ival;std::vector<double> dvec;
}

18.26

  1. 所有可见的名字:
函数内:int dval;double cval;
类内:int *ival;std::vector<double> dvec;void print(std::vector<double>);
Derived:void Derived::print(std::string) const;std::string sval;double Derived::dval;
Base1:void Base1::print(int) const;int Base1::ival;double Base1::dval;char Base1::cval;
Base2:void Base2::print(double) const;int Base2::ival;double fval;char Base2::cval;
全局作用域:int ival;double dval;
dval    cval    ival    print都是继承自多个基类。
dval:Derived::dval  Base1::dval
cval:Base1::cval    Base2::cval
ival:Base1::ival    Base2::ival
print:Derived::print    Base1::print    Base2::print
void MI::foo(double cval)
{int dval;dval=Base1::dval+Derived::dval;
}
void MI::foo(double cval)
{int dval;Base2::fval=dvec.back();
}
void MI::foo(double cval)
{int dval;sval[0]=Base1::cval;
}

18.28

无需前缀限定符:
    Derived1::bar
     Derived2::ival
需要前缀限定符:
     Derived1::foo
     Derived2::foo
     Base::bar
     Base::ival
     Derived1::cval
     Derived2::cval

18.29

构造函数顺序:Class() Base() D1() D2() MI() Class() Final()
析构函数顺序:Final() Class() MI() D2() D1() Base() Class()
2. 1个base部分,两个Class部分。
3.
pb=new Class错误,不存在基类指针向派生类的隐式转换
pc=new Final错误,Class接口的使用会导致二义性错误
pmi=pb错误,不存在基类指针向派生类的隐式转换
pd2=pmi正确

18.30

这样定义的话,由于存在歧义,直接基类Class在Final中无法访问
class Class{};
class Base:public Class
{public:Base()=default;Base(const Base &b):i(b.i) {}Base(const int &ri):i(ri) {}private:int i;
};
class D1:public virtual Base
{public:D1()=default;D1(const D1 &d):Base(d) {}D1(const int &ri):Base(ri) {}
};
class D2:public virtual Base
{public:D2()=default;D2(const D2 &d):Base(d) {}D2(const int &ri):Base(ri) {}
};
class MI:public D1,public D2
{public:MI()=default;MI(const MI &mi):Base(mi),D1(mi),D2(mi) {}MI(const int &ri):Base(ri),D1(ri),D2(ri) {}
};
class Final:public MI,public Class
{public:Final()=default;Final(const Final &fi):Base(fi),MI(fi),Class() {}Final(const int &ri):Base(ri),MI(ri),Class() {}
};

这篇关于c++ primer中文版第五版作业第十八章的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/788693

相关文章

C++中实现调试日志输出

《C++中实现调试日志输出》在C++编程中,调试日志对于定位问题和优化代码至关重要,本文将介绍几种常用的调试日志输出方法,并教你如何在日志中添加时间戳,希望对大家有所帮助... 目录1. 使用 #ifdef _DEBUG 宏2. 加入时间戳:精确到毫秒3.Windows 和 MFC 中的调试日志方法MFC

深入理解C++ 空类大小

《深入理解C++空类大小》本文主要介绍了C++空类大小,规定空类大小为1字节,主要是为了保证对象的唯一性和可区分性,满足数组元素地址连续的要求,下面就来了解一下... 目录1. 保证对象的唯一性和可区分性2. 满足数组元素地址连续的要求3. 与C++的对象模型和内存管理机制相适配查看类对象内存在C++中,规

在 VSCode 中配置 C++ 开发环境的详细教程

《在VSCode中配置C++开发环境的详细教程》本文详细介绍了如何在VisualStudioCode(VSCode)中配置C++开发环境,包括安装必要的工具、配置编译器、设置调试环境等步骤,通... 目录如何在 VSCode 中配置 C++ 开发环境:详细教程1. 什么是 VSCode?2. 安装 VSCo

C++11的函数包装器std::function使用示例

《C++11的函数包装器std::function使用示例》C++11引入的std::function是最常用的函数包装器,它可以存储任何可调用对象并提供统一的调用接口,以下是关于函数包装器的详细讲解... 目录一、std::function 的基本用法1. 基本语法二、如何使用 std::function

作业提交过程之HDFSMapReduce

作业提交全过程详解 (1)作业提交 第1步:Client调用job.waitForCompletion方法,向整个集群提交MapReduce作业。 第2步:Client向RM申请一个作业id。 第3步:RM给Client返回该job资源的提交路径和作业id。 第4步:Client提交jar包、切片信息和配置文件到指定的资源提交路径。 第5步:Client提交完资源后,向RM申请运行MrAp

【C++ Primer Plus习题】13.4

大家好,这里是国中之林! ❥前些天发现了一个巨牛的人工智能学习网站,通俗易懂,风趣幽默,忍不住分享一下给大家。点击跳转到网站。有兴趣的可以点点进去看看← 问题: 解答: main.cpp #include <iostream>#include "port.h"int main() {Port p1;Port p2("Abc", "Bcc", 30);std::cout <<

C++包装器

包装器 在 C++ 中,“包装器”通常指的是一种设计模式或编程技巧,用于封装其他代码或对象,使其更易于使用、管理或扩展。包装器的概念在编程中非常普遍,可以用于函数、类、库等多个方面。下面是几个常见的 “包装器” 类型: 1. 函数包装器 函数包装器用于封装一个或多个函数,使其接口更统一或更便于调用。例如,std::function 是一个通用的函数包装器,它可以存储任意可调用对象(函数、函数

C++11第三弹:lambda表达式 | 新的类功能 | 模板的可变参数

🌈个人主页: 南桥几晴秋 🌈C++专栏: 南桥谈C++ 🌈C语言专栏: C语言学习系列 🌈Linux学习专栏: 南桥谈Linux 🌈数据结构学习专栏: 数据结构杂谈 🌈数据库学习专栏: 南桥谈MySQL 🌈Qt学习专栏: 南桥谈Qt 🌈菜鸡代码练习: 练习随想记录 🌈git学习: 南桥谈Git 🌈🌈🌈🌈🌈🌈🌈🌈🌈🌈🌈🌈🌈�

【C++】_list常用方法解析及模拟实现

相信自己的力量,只要对自己始终保持信心,尽自己最大努力去完成任何事,就算事情最终结果是失败了,努力了也不留遗憾。💓💓💓 目录   ✨说在前面 🍋知识点一:什么是list? •🌰1.list的定义 •🌰2.list的基本特性 •🌰3.常用接口介绍 🍋知识点二:list常用接口 •🌰1.默认成员函数 🔥构造函数(⭐) 🔥析构函数 •🌰2.list对象

06 C++Lambda表达式

lambda表达式的定义 没有显式模版形参的lambda表达式 [捕获] 前属性 (形参列表) 说明符 异常 后属性 尾随类型 约束 {函数体} 有显式模版形参的lambda表达式 [捕获] <模版形参> 模版约束 前属性 (形参列表) 说明符 异常 后属性 尾随类型 约束 {函数体} 含义 捕获:包含零个或者多个捕获符的逗号分隔列表 模板形参:用于泛型lambda提供个模板形参的名