《C++ Primer》第15章 15.8节习题答案

《C++ Primer》第15章 面向对象程序设计

15.8节 容器与继承 习题答案

练习15.27:重新定义你的Bulk_quote类,令其继承构造函数。

【出题思路】

本题练习继承构造函数的定义。

【解答】

#include <iostream>
#include <string>
#include <ostream>

using namespace std;

class Quote
{
public:
    Quote() = default;
    Quote(const std::string &book = "", double sales_price = 0.0)
    :bookNo(book), price(sales_price)
    {
        cout << "Quote constructor is running===========" << endl;
    }

    string isbn() const
    {
        return bookNo;
    }

    //返回给定数量的书籍的销售总额,派生类改写并使用不同的折扣计算方法
    virtual double net_price(std::size_t n) const
    {
        return n * price;
    }

    virtual void debug()
    {
        cout << "bookNo = " << bookNo << " price = " << price << endl;
    }

    virtual ~Quote()
    {
        cout << "Quote destructor is running=========" << endl;
    }

    friend ostream &operator << (ostream &, Quote &);

private:
    std::string bookNo;//书籍的ISBN编号

protected:
    double price = 0.0;//代表普通状态下不打折的价格
};

ostream& operator << (ostream &os, Quote &e)
{
    os << "\tUsing operator << (ostram &, Quote &);" << endl;
    return os;
}
class Disc_quote: public Quote
{
public:
    Disc_quote(const string &book = "", double sales_price = 0.0, size_t qty = 0, double disc = 0.0)
    :Quote(book, sales_price), quantity(qty), discount(disc)
    {

    }
    double net_price(size_t cnt) const = 0;

protected:
    size_t quantity;
    double discount;
};

class Bulk_quote: public Disc_quote
{
public:
    using Disc_quote::Disc_quote;
    double net_price(size_t cnt) const
    {
        if(cnt > quantity)
            return cnt * discount * price;
        else
            return cnt * price;
    }

    ~Bulk_quote()
    {
        cout << "Bulk_quote destructor is running" << endl;
    }

private:
    size_t min_qty;
    double discount;
};

ostream &operator << (ostream &os, Bulk_quote &bq)
{
    os << "\tUsing operator << (ostram &, Bulk_quote &)" << endl;
    return os;
}

int main(int argc, const char *argv[])
{
    Quote base("C++ Primer", 128.0);
    Bulk_quote bulk("Core Python Programming", 89, 5, 0.9);
    cout << base << endl;
    cout << bulk << endl;
    return 0;
}

运行结果:

 练习15.28:定义一个存放Quote对象的vector,将Bulk_quote对象传入其中。计算vector中所有元素总的net_price。

【出题思路】

本题是在容器中放置对象的使用练习。

【解答】

#include <iostream>
#include <string>
#include <ostream>
#include <vector>

using namespace std;

class Quote
{
public:
    Quote() = default;
    Quote(const std::string &book = "", double sales_price = 0.0)
    :bookNo(book), price(sales_price)
    {
        cout << "Quote constructor is running========" << this << endl;
    }

    string isbn() const
    {
        return bookNo;
    }

    //返回给定数量的书籍的销售总额,派生类改写并使用不同的折扣计算方法
    virtual double net_price(std::size_t n) const
    {
        return n * price;
    }

    virtual void debug()
    {
        cout << "bookNo = " << bookNo << " price = " << price << endl;
    }

    virtual ~Quote()
    {
        cout << "Quote destructor is running=========" << this << endl;
    }

    friend ostream &operator << (ostream &, Quote &);

private:
    std::string bookNo;//书籍的ISBN编号

protected:
    double price = 0.0;//代表普通状态下不打折的价格
};

ostream& operator << (ostream &os, Quote &e)
{
    os << "\tUsing operator << (ostram &, Quote &);" << endl;
    return os;
}
class Disc_quote: public Quote
{
public:
    Disc_quote(const string &book = "", double sales_price = 0.0, size_t qty = 0, double disc = 0.0)
    :Quote(book, sales_price), quantity(qty), discount(disc)
    {

    }
    double net_price(size_t cnt) const = 0;

protected:
    size_t quantity;
    double discount;
};

class Bulk_quote: public Disc_quote
{
public:
    using Disc_quote::Disc_quote;
    double net_price(size_t cnt) const
    {
        if(cnt > quantity)
            return cnt * discount * price;
        else
            return cnt * price;
    }

    ~Bulk_quote()
    {
        cout << "Bulk_quote destructor is running " << this << endl;
    }

private:
    size_t min_qty;
    double discount;
};

ostream &operator << (ostream &os, Bulk_quote &bq)
{
    os << "\tUsing operator << (ostram &, Bulk_quote &)" << endl;
    return os;
}

int main(int argc, const char *argv[])
{
    vector<Quote> itemVec;
    for(size_t i = 0; i != 5; ++i)
    {
        Bulk_quote item("C++ Primer", 6, 5, 0.5);
        itemVec.push_back(item);
    }

    double sum = 0;
    for(vector<Quote>::iterator iter = itemVec.begin(); iter != itemVec.end(); ++iter)
    {
        sum += iter->net_price(10);//调用Quote::net_price
    }
    cout << sum << endl;
    return 0;
}

运行结果:

 练习15.29:再运行一次你的程序,这次传入Quote对象的shared_ptr。如果这次计算出的总额与之前的程序不一致,解释为什么;如果一致,也请说明原因。

【出题思路】

本题是在容器中放置指针的使用练习,与放置对象的过程结果存在差异。

【解答】

p527和p537  在C++语言中,当我们使用基类的引用(或指针)调用一个虚函数时将发生动态绑定。普通对象调用不会发生动态绑定
vector<shared_ptr<Quote>> itemVec;
程序产生的结果会存在差异。因为当通过Quote类型的对象调用虚函数net_price时,不实行动态绑定,调用的是Quote类中定义的版本;而通过Quote类型的指针调用虚函数net_price,实行动态绑定,而该指针实际指向Bulk_quote类中定义的版本。

练习15.30:编写你自己的Basket类,用它计算上一个练习中交易记录的总价格。

【出题思路】

本题是类构造编程练习。

【解答】

#include <iostream>
#include <string>
#include <ostream>
#include <vector>
#include <memory>
#include <set>//multiset

using namespace std;

class Quote
{
public:
    Quote() = default;
    Quote(const std::string &book = "", double sales_price = 0.0)
    :bookNo(book), price(sales_price)
    {
        cout << "Quote constructor is running===========" << endl;
    }

    string isbn() const
    {
        return bookNo;
    }

    //返回给定数量的书籍的销售总额,派生类改写并使用不同的折扣计算方法
    virtual double net_price(std::size_t n) const
    {
        return n * price;
    }

    virtual void debug()
    {
        cout << "bookNo = " << bookNo << " price = " << price << endl;
    }

    virtual ~Quote()
    {
        cout << "Quote destructor is running=========" << endl;
    }

    friend ostream &operator << (ostream &, Quote &);

private:
    std::string bookNo;//书籍的ISBN编号

protected:
    double price = 0.0;//代表普通状态下不打折的价格
};

ostream& operator << (ostream &os, Quote &e)
{
    os << "\tUsing operator << (ostram &, Quote &);" << endl;
    return os;
}

// calculate and print the price for the given number of copies, applying any discounts
double print_total(ostream &os, const Quote &item, size_t n)
{
    // depending on the type of the object bound to the item parameter
    // calls either Quote::net_price or Bulk_quote::net_price
    double ret = item.net_price(n);
    os << "ISBN: " << item.isbn() // calls Quote::isbn
    << " # sold: " << n << " total due: " << ret << endl;
    return ret;
}


class Basket
{
public:
    //Basket使用合成的默认构造函娄和拷贝制成员
    void add_item(const std::shared_ptr<Quote> &sale)
    {
        items.insert(sale);
    }
    //打印每本书的总价和购物篮中所有书的总价
    double total_receipt(std::ostream &) const;

private:
    //该函数用于比较shared_ptr,multiset成员会用到它
    static bool compare(const std::shared_ptr<Quote> &lhs, const std::shared_ptr<Quote> &rhs)
    {
        return lhs->isbn() < rhs->isbn();
    }
    //multiset保存多个报价,按照compare成员排序
    std::multiset<std::shared_ptr<Quote>, decltype(compare) *> items{compare};
};

double Basket::total_receipt(ostream &os) const
{
    double sum = 0.0;//保存实时计算出的总价格
    //iter指向ISBN相同的一批元素中的第一个
    //upper_bound返回一个迭代器,该迭代器指向这批元素的最后一个的下一位置
    for(auto iter = items.cbegin(); iter != items.cend(); iter = items.upper_bound(*iter))
    {
        //我们知道在当前的Basket中至少有一个该关键字的元素
        //打印该书籍对应的项目
        sum += print_total(os, **iter, items.count(*iter));
    }
    os << "Total Sale: " << sum << endl;//打印最终的总价格
    return sum;
}

int main(int argc, const char *argv[])
{
    Basket sale;
    sale.add_item(shared_ptr<Quote>(new Quote("123", 25)));
    sale.add_item(shared_ptr<Quote>(new Quote("456", 35)));
    sale.add_item(shared_ptr<Quote>(new Quote("789", 45)));

    sale.total_receipt(cout);

    return 0;
}

运行结果:

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值