zoukankan      html  css  js  c++  java
  • C++ Primer第5版 第十八章课后练习答案

    练习18.1

    (a)range_error;
    (b)exception。
    throw p,此时抛出的为指向局部对象的指针

    练习18.2

    p的内存没有释放,导致内存泄露

    练习18.3

    使用类对象

    class vec_size
    {
    public:
        vec_size():p(nullptr){}
        vec_size(size_t size):p(new int[size]){}
        ~vec_size()
        {
            delete p;
        }
    private:
        int* p;
    };

    使用智能指针

    std::shared_ptr<int> p(new int[v.size()], [](int* p) { delete[] p; });

    练习18.4

    应该把异常类继承链层次最底端的类放在前面,而将继承链层次最顶端的类放在后面。

    练习18.5

    int main(int argc, char* argv[])
    {
        try{}
        catch (const std::bad_cast& bc) {
            cout << bc.what();
            abort();
        }
        catch (const std::bad_alloc& ba) {
            cout << ba.what();
            abort();
        }
        catch (const std::overflow_error& oe) {
            cout << oe.what();
            abort();
        }
        catch (const std::underflow_error& ue) {
            cout << ue.what();
            abort();
        }
        catch (const std::range_error& re) {
            cout << re.what();
            abort();
        }
        catch (const std::runtime_error&re) {
            cout << re.what();
            abort();
        }
        catch (const std::domain_error&de) {
            cout << de.what();
            abort();
        }
        catch (const std::invalid_argument&ia) {
            cout << ia.what();
            abort();
        }
        catch (const std::out_of_range&oor) {
            cout << oor.what();
            abort();
        }
        catch (const std::length_error&le) {
            cout << le.what();
            abort();
        }
        catch (const std::logic_error&le) {
            cout << le.what();
            abort();
        }
        catch (const std::exception&e) {
            cout << e.what();
            abort();
        }
    }

    练习18.6

    (a)throw exceptionType *pet;

    (b)throw exception();//可以捕获所有异常

    (c)int a=1;throw a;

    练习18.7

    template <typename T>
    Blob<T>::Blob()try :data(std::make_shared<vector<T>()>) {}
    catch(const std::bad_alloc &e){
        handle_out_of_memory(e);
    }
    template<typename T>
    Blob<T>::Blob(std::initializer_list<T> il) try :data(make_shared<vector<T>>(il)) {}
    catch(const std::bad_alloc &e){
        handle_out_of_memory(e);
    }
    template <typename T>
    BlobPtr<T>::BlobPtr()try:curr(0){}
    catch (const std::bad_alloc& e) {
        handle_out_of_memory(e);
    }
    template <typename T>
    BlobPtr<T>::BlobPtr(Blob<T> &a, size_t sz = 0)try : wptr(a.data), curr(sz) {}
    catch (const std::bad_alloc& e) {
        handle_out_of_momory(e);
    }

    练习18.8

     

    练习18.9

    #ifndef SALES_DATA_H
    #define SALES_DATA_H
    #include <string>
    #include <ostream>
    template<class T>struct std::hash;
    
    struct out_of_stock :public std::runtime_error
    {
        explicit out_of_stock(const std::string& s) :std::runtime_error(s) {}
    };
    
    struct isbn_mismatch :public std::logic_error
    {
        explicit isbn_mismatch(const std::string& s) :std::logic_error(s) {}
        isbn_mismatch(const std::string& s, const std::string& ls, const std::string& rs)
            :std::logic_error(s), left(ls), right(rs)
        {}
        std::string left;
        std::string right;
    };
    
    class Sales_data {
        friend struct std::hash<Sales_data>;
        friend Sales_data operator+(Sales_data& lhs, Sales_data& rhs);
        friend Sales_data operator-(Sales_data& lhs, Sales_data& rhs);
        friend std::istream& operator>>(std::istream& is, Sales_data& it);
        friend std::ostream& operator<<(std::ostream& os, const Sales_data& it);
        friend bool operator==(const Sales_data& lhs, const Sales_data& rhs);
    private:
        string bookNo;
        unsigned units_sold = { 0 };
        double revenue = { 0.0 };
    public:
        const string& isbn() const { return bookNo; }
        Sales_data& operator+=(const Sales_data& rhs) {
            if (isbn() != rhs.isbn())
                throw isbn_mismatch("wrong isbns", isbn(), rhs.isbn());
            units_sold += rhs.units_sold;
            revenue += rhs.revenue;
            return *this;
        }
        Sales_data& operator-=(const Sales_data& rhs) {
            if (isbn() != rhs.isbn())
                throw isbn_mismatch("wrong isbns", isbn(), rhs.isbn());
            units_sold -= rhs.units_sold;
            revenue -= rhs.revenue;
            return *this;
        }
        Sales_data(string bn, unsigned us = 0, double re = 0.0) :bookNo(bn), units_sold(us), revenue(re) { std::cout << "Sales_data(string bn, unsigned us = 0, double re = 0.0)" << std::endl;}
        Sales_data() :Sales_data("") { std::cout << "Sales_data()" << std::endl; }
        Sales_data(std::istream& is) :Sales_data() { is>> *this; std::cout << "Sales_data(istream& is)" << std::endl; }
        Sales_data& operator=(string&)noexcept;
        explicit operator string() const { return bookNo; }
        explicit operator double() const { return revenue; }
    };
    
    Sales_data operator+(const Sales_data& lhs,const  Sales_data& rhs) {
        if (lhs.isbn() != rhs.isbn())
            throw isbn_mismatch("wrong isbns", lhs.isbn(), rhs.isbn());
        Sales_data sum = lhs;
        sum += rhs;
        return sum;
    }
    
    Sales_data operator-(Sales_data& lhs, Sales_data& rhs) {
        if (lhs.isbn() != rhs.isbn())
            throw isbn_mismatch("wrong isbns", lhs.isbn(), rhs.isbn());
        Sales_data sum = lhs;
        sum -= rhs;
        return sum;
    }
    
    std::istream & operator>>(std::istream& is, Sales_data& it) {
        is >> it.bookNo >> it.units_sold >> it.revenue;
        if (!is)
            it = Sales_data();
        return is;
    }
    
    std::ostream& operator<<(std::ostream& os, const Sales_data& it) {
        os << it.isbn() << " " << it.units_sold << " " << it.revenue;
        return os;
    }
    
    inline bool operator==(const Sales_data& lhs, const Sales_data& rhs)
    {
        return lhs.units_sold == rhs.units_sold &&
            lhs.revenue == rhs.revenue &&
            lhs.isbn() == rhs.isbn();
    }
    
    Sales_data& Sales_data::operator=(string& s)noexcept
    {
        bookNo = s;
        units_sold = 0;
        revenue = 0;
        return *this;
    }
    namespace std {
        template<>
        struct hash<Sales_data>
        {
            typedef size_t result_type;
            typedef Sales_data argument_type;
            size_t operator()(const Sales_data& s)const;
        };
        size_t hash<Sales_data>::operator()(const Sales_data& s) const
        {
            return hash<string>()(s.bookNo)^ hash<unsigned>()(s.units_sold)^ hash<double>()(s.revenue);
        }
    }
    #endif // !SALES_DATA_H

    练习18.10

    Sales_data operator+(const Sales_data& lhs,const  Sales_data& rhs) {
        if (lhs.isbn() != rhs.isbn())
            throw isbn_mismatch("wrong isbns", lhs.isbn(), rhs.isbn());
        Sales_data sum = lhs;
        sum += rhs;
        return sum;
    }
    
    Sales_data operator+(const Sales_data& lhs,const  Sales_data& rhs) {
        Sales_data sum = lhs;
        sum += rhs;
        return sum;
    }

    出现一个未被捕获的异常时,程序将会执行terminate。

    练习18.11

    what中如果抛出异常,需要try catch捕获,再调用what,一直循环,直达内存耗尽。

    练习18.12

    #include <fstream>
    using std::ifstream;
    using std::ofstream;
    #include <iostream>
    using std::cin;
    using std::cout;
    using std::endl;
    #include <map>
    using std::map;
    using std::multimap;
    #include <set>
    using std::multiset;
    using std::set;
    #include <sstream>
    using std::istringstream;
    #include <string>
    using std::string;
    #include <unordered_map>
    using std::unordered_map;
    #include <vector>
    #include "StrVec.h"
    #include <algorithm>
    using std::vector;
    #ifndef TEXTQUERT_H_
    #define TEXTQUERT_H_
    #include "DebugDelete.h"
    namespace chapter10 {
        class QueryResult;
        class TextQuery
        {
            friend class QueryResult;
        public:
            TextQuery() :text(new StrVec, DebugDelete("TextQuery::StrVec")), query_words(new map<string, std::shared_ptr<set<size_t>>>, DebugDelete("TextQuery::map<string, std::shared_ptr<set<size_t>>>")) {}
            TextQuery(ifstream& ifs);
            QueryResult query(string s) const;
            ~TextQuery();
    
        private:
            std::shared_ptr <StrVec> text;
            std::shared_ptr<map<string, std::shared_ptr<set<size_t>>>> query_words;
        };
    
        class QueryResult
        {
        public:
            friend std::ostream& print(std::ostream& os, const QueryResult qr);
            using QueryIterator = set<size_t>::iterator;
        public:
            QueryResult(string& w, std::shared_ptr<set<size_t>> n, std::shared_ptr<StrVec> i) :word(w), nos(new set<size_t>, DebugDelete("QueryResult::set<size_t>")), inputs(new StrVec, DebugDelete("QueryResult::StrVec")) {
                nos = n;
                inputs = i;
            }
            ~QueryResult();
            QueryIterator begin() { return nos->begin(); }
            QueryIterator end() { return nos->end(); }
            std::shared_ptr <StrVec> get_file() { return inputs; }
        private:
            string word;
            std::shared_ptr<set<size_t>> nos;
            std::shared_ptr<StrVec> inputs;
        };
    
        QueryResult::~QueryResult()
        {
        }
    
        inline TextQuery::TextQuery(ifstream& ifs) : text(new StrVec, DebugDelete("TextQuery::StrVec")), query_words(new map<string, std::shared_ptr<set<size_t>>>, DebugDelete("TextQuery::map<string, std::shared_ptr<set<size_t>>>"))
        {
            size_t size = 0;
            if (ifs) {
                for (string line; getline(ifs, line, '.'); ++size)
                {
                    text->push_back(line);
                    istringstream iss(line);
                    size = text->size();
                    for (string text, word; iss >> text; word.clear()) {
                        std::remove_copy_if(text.begin(), text.end(),
                            std::back_inserter(word), ispunct);
                        // use reference avoid count of shared_ptr add.
                        auto& nos = (*query_words)[word];
                        if (!nos) nos.reset(new std::set<size_t>);
                        nos->insert(size);
                    }
                }
            }
        }
    
        inline QueryResult TextQuery::query(string s) const {
            static std::shared_ptr<std::set<size_t>> nodate(new std::set<size_t>, DebugDelete("TextQuery::std::set<size_t>"));
            auto found = query_words->find(s);
            if (found == query_words->end()) {
                cout << s + " is not in the text" << endl;
                return QueryResult(s, nodate, text);
            }
            else
                return QueryResult(s, found->second, text);
        }
        TextQuery::~TextQuery()
        {
        }
    
        std::ostream& print(std::ostream& os, const QueryResult qr) {
            os << qr.word << " occurs " << qr.nos->size() << " times" << endl;
            for (auto i : *qr.nos) {
                os << "	(line " << i + 1 << ") " << qr.inputs->at(i) << std::endl;
            }
            return os;
        }
    }
    #endif // !TEXTQUERT_H_
    #ifndef _QUERY_H_
    #define _QUERY_H_
    #include "TextQuery.h"
    namespace chapter15
    {
        class Query_base
        {
            friend class Query;
        protected:
            virtual ~Query_base() = default;
        private:
            virtual chapter10::QueryResult eval(const chapter10::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&);
            chapter10::QueryResult eval(const chapter10::TextQuery& t)const {
                return q->eval(t);
            }
            std::string rep()const {
                std::cout << "QueryResult::rep" << std::endl;
                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;
            WordQuery(const std::string& s) :query_word(s) {
                std::cout << "WordQuery::WordQuery" << std::endl;
            }
            chapter10::QueryResult eval(const chapter10::TextQuery& t)const {
                return t.query(query_word);
            }
            std::string rep()const {
                std::cout << "WordQuery::rep" << std::endl;
                return query_word;
            }
            std::string query_word;
        };
    
        Query::Query(const std::string& s) :q(new WordQuery(s)) {
            std::cout << "Query::Query" << std::endl;
        }
    
        class NotQuery :public Query_base
        {
            friend Query operator~(const Query&);
            NotQuery(const Query& q) :query(q) {
                std::cout << "NotQuery::NotQuery" << std::endl;
            }
            std::string rep()const {
                std::cout << "NotQuery::rep" << std::endl;
                return"~(" + query.rep() + ")";
            }
            chapter10::QueryResult eval(const chapter10::TextQuery&)const;
            Query query;
        };
    
        inline Query operator~(const Query& operand)
        {
            return std::shared_ptr<Query_base>(new NotQuery(operand));
        }
    
        chapter10::QueryResult NotQuery::eval(const chapter10::TextQuery& text) const
        {
            auto result = query.eval(text);
            auto ret_lines = std::make_shared<set<size_t>>();
            auto beg = result.begin(), end = result.end();
            auto sz = result.get_file()->size();
            for (size_t n = 0; n != sz; ++n) {
                if (beg == end || *beg != n)
                    ret_lines->insert(n);
                else if (beg != end)
                    ++beg;
            }
            string s = rep();
            return chapter10::QueryResult(s, ret_lines, result.get_file());
        }
    
        class BinaryQuery :public Query_base
        {
        protected:
            BinaryQuery(const Query& l, const Query& r, std::string s) :lhs(l), rhs(r), opSym(s) {
                std::cout << "BinaryQuery::BinaryQuery" << std::endl;
            }
            std::string rep() const
            {
                std::cout << "BinaryQuery::rep" << std::endl;
                return "(" + lhs.rep() + " " + opSym + " " + rhs.rep() + ")";
            }
            Query lhs, rhs;
            std::string opSym;
        };
    
        class AndQuery : public BinaryQuery
        {
            friend Query operator& (const Query&, const Query&);
            AndQuery(const Query& left, const Query& right) : BinaryQuery(left, right, "&") {
                std::cout << "AndQuery::AndQuery" << std::endl;
            }
            chapter10::QueryResult eval(const chapter10::TextQuery&) const;
        };
    
        inline Query operator& (const Query& lhs, const Query& rhs)
        {
            return std::shared_ptr<Query_base>(new AndQuery(lhs, rhs));
        }
    
        chapter10::QueryResult AndQuery::eval(const chapter10::TextQuery& text) const
        {
            auto right = rhs.eval(text), left = lhs.eval(text);
            auto ret_lines = std::make_shared<set<size_t>>();
            set_intersection(left.begin(), left.end(), right.begin(), right.end(), inserter(*ret_lines, ret_lines->begin()));
            string s = rep();
            return chapter10::QueryResult(s, ret_lines, left.get_file());
        }
    
        class OrQuery : public BinaryQuery
        {
            friend Query operator| (const Query&, const Query&);
            OrQuery(const Query& left, const Query& right) : BinaryQuery(left, right, "|") {
                std::cout << "OrQuery::OrQuery" << std::endl;
            }
            chapter10::QueryResult eval(const chapter10::TextQuery&) const;
        };
    
        inline Query operator| (const Query& lhs, const Query& rhs)
        {
            return std::shared_ptr<Query_base>(new OrQuery(lhs, rhs));
        }
    
        chapter10::QueryResult OrQuery::eval(const chapter10::TextQuery& text) const
        {
            auto right = rhs.eval(text), left = lhs.eval(text);
            auto ret_lines = std::make_shared<set<size_t>>(left.begin(), left.end());
            ret_lines->insert(right.begin(), right.end());
            string s = rep();
            return chapter10::QueryResult(s, ret_lines, left.get_file());
        }
    
        std::ostream& operator<<(std::ostream& os, const Query& query) {
            return os << query.rep();
        }
    }
    #endif // !_QUERY_H_

    练习18.13

    在文件中使用静态声明的时候使用未命名的命名空间

    练习18.14

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

    练习18.15

    using声明简单地令名字在局部作用域内有效,using指示是令整个命名空间的所有内容变得有效

    练习18.16

    练习18.17

    namespace Exercise {
        int ivar = 0;
        double dvar = 0;
        const int limit = 1000;
    }
    int ivar = 0;
    using Exercise::ivar;//隐藏了全局ivar
    using Exercise::dvar;
    using Exercise::limit;
    void manip() {
        double var = 3.1416;
        int iobj = limit + 1;
        ++ivar;
        ++::ivar;
    }
    namespace Exercise {
        int ivar = 0;
        double dvar = 0;
        const int limit = 1000;
    }
    int ivar = 0;
    //using Exercise::ivar;//隐藏了全局ivar
    //using Exercise::dvar;
    //using Exercise::limit;
    void manip() {
        using namespace Exercise;
        double var = 3.1416;
        int iobj = limit + 1;
        ++ivar;//二义性错误:是全局的ivar还是Exercise::ivar
        ++::ivar;//是全局的ivar
    }

    练习18.18

    当mem1是一个string时程序会优先查找string库使用swap的string版本,当mem1时int时使用std::swap的int版本

    练习18.19

    直接调用std::swap模版而不会去查找所属的命名空间

    练习18.20

    候选函数:全部

    namespace primerLib
    {
        void compute() {}//不可行  
        void compute(const void*) {}//可行,0->NULL  
    }
    using primerLib::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)版本最佳匹配  
    }

    候选函数:primerLib::compute(),primerLib::compute(const void*)

     
    
    namespace primerLib
    {
        void compute() {}//不可行  
        void compute(const void*) {}//可行,0->NULL,最佳匹配  
    }
    using primerLib::compute;
    void compute(int) {}//被屏蔽
    void compute(double, double = 1.1) {}//被屏蔽  
    void compute(char*, char* = 0) {}//被屏蔽
    
    void f()
    {
        compute(0);//与compute(const void*)版本最佳匹配  
    }

     练习18.21

    (a) class CADVehicle : public CAD, Vehicle { ... };//公有继承CAD,私有继承Vehicle
    (b) class DbiList : public List, public List { ... };//公有继承List,重复继承
    (c) class iostream : public istream, public ostream { ... };//公有继承istream,公有继承ostream

    练习18.22

    ((A->B->C)|((X|Y)->Z))->MI

    练习18.23

    都允许

    练习18.24

    ZooAnimal *pza=new Panda("Ying_yang");
    pza->print();正确
    pza->highlight() 错误;
    pza->toes() 错误;
    pza->duddle() 错误;
    delete pza 正确。

    练习18.25

    Base1 *pb1 = new MI;
    Base2 *pb2 = new MI;
    D1 *pd1 = new MI;
    D2 *pd2 = new MI;
    (a) pb1->print();//MI::print() 
    (b) pd1->print();//MI::print()
    (c) pd2->print();//MI::print()
    (d) delete pb2;//MI::~MI() 
    (e) delete pd1;//MI::~MI()
    (f) delete pd2;//MI::~MI()

    练习18.26

    会产生二义性

    struct MI : public Derived, public Base2 {
    
        void print(std::vector<double>) {};
        void print(int x) {
            Base1::print(x);
        }
    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可见

    (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)

    dval=Base1::dval+Derived::dval;

    (d)

    fval=dvec.back();

    (e)

    sval[0]=Base1::cval;

    练习18.28

    bar,ival能直接访问

    foo,cval不能直接访问

    练习18.29

    (a)构造((Class->Base->(D1|D2)->MI)|Class)->Final,析构Final->(Class|(MI->(D1|D2)->Base->Class))

    (b)一个Base部分,两个Class部分

    (c)

      (a)错误,Class是Base的基类,而pb是Base类

      (b)正确,基类Class可以指向所有子类

      (c)错误、pb是Base类,MI是Base的子类

      (d)正确、D2是MI的基类

    练习18.30

    class Class { 
    public:
        Class(){} 
    
    };
    class Base : public Class {
    public:
        Base() :ival(0) {}
        Base(const Base& b) {
            ival = b.ival;
        }
        Base(int i) {
            ival = i;
        }
    protected:
        int ival;
    };
    class D1 : virtual public Base {
    public:
        D1() :Base() {}
        D1(const D1& d1) :Base(d1) {}
        D1(int i) :Base(ival) {}
    };
    class D2 : virtual public Base {
    public:
        D2() :Base() {}
        D2(const D1& d1) :Base(d1) {}
        D2(int i) :Base(ival) {}
    };
    class MI : public D1, public D2 {
    public:
        MI() = default;
        MI(const MI& m) :D1(m), D2(m) {}
        MI(int i) : D1(i), D2(i) { cout << "MI(int)" << endl; }
    };
    class Final : public MI, public Class {
    public:
        Final() = default;
        Final(const Final& f) : MI(f), Class() {}
        Final(int i) : MI(i), Class() { cout << "MI(int)" << endl; }
    };
    class Class { 
    public:
        Class(){} 
    
    };
    class Base : public Class {
    public:
        Base() :ival(0) {}
        Base(const Base& b) {
            ival = b.ival;
        }
        Base(int i) {
            ival = i;
        }
    protected:
        int ival;
    };
    class D1 : virtual public Base {
    public:
        D1() :Base() {}
        D1(const D1& d1) :Base(d1) {}
        D1(int i) :Base(ival) {}
    };
    class D2 : virtual public Base {
    public:
        D2() :Base() {}
        D2(const D1& d1) :Base(d1) {}
        D2(int i) :Base(ival) {}
    };
    class MI : public D1, public D2 {
    public:
        MI() = default;
        MI(const MI& m) :D1(m), D2(m) {}
        MI(int i) : D1(i), D2(i) { cout << "MI(int)" << endl; }
    };
    class Final : public MI, public Class {
    public:
        Final() = default;
        Final(const Final& f) : MI(f), Class() {}
        Final(int i) : MI(i), Class() { cout << "MI(int)" << endl; }
    };
  • 相关阅读:
    天津大学2021年数学分析考研试卷
    天津大学2021年高等代数考研试卷
    太原理工大学2021年数学分析考研试卷
    太原理工大学2021年高等代数考研试卷
    苏州大学2021年数学分析考研试卷
    苏州大学2021年高等代数考研试卷
    2021年八省联考数学试题参考解答
    四川大学2021年数学分析考研试卷
    四川大学2021年高等代数考研试卷
    首都师范大学2021年数学分析考研试卷
  • 原文地址:https://www.cnblogs.com/GodZhuan/p/14136976.html
Copyright © 2011-2022 走看看