《C++ Primer》十五章面向对象编程例题1

头文件.h

#ifndef BASKET_H
#define BASKET_H

#include <iostream>
#include <string>
#include <set>
#include <map>
#include <utility>
#include <cstddef>
#include <stdexcept>

// Item sold at an undiscounted price
// derived classes will define various discount strategies
class Item_base 
{
	friend std::istream& operator>>(std::istream&, Item_base&);
	friend std::ostream& operator<<(std::ostream&, const Item_base&);
public:
	//都定义了clone函数来返回一个自身的副本,在句柄类初始化时,会用得到它们
    virtual Item_base* clone() const 
    { 
		return new Item_base(*this); 
	}
public:
	//构造函数
    Item_base(const std::string &book = "", 
              double sales_price = 0.0):
                     isbn(book), price(sales_price) { }
	//返回ISBN号
    std::string book() const { return isbn; }

    // returns total sales price for a specified number of items
    // derived classes will override and apply different discount algorithms
	//基类不需要折扣
    virtual double net_price(std::size_t n) const 
               { return n * price; }

    // no work, but virtual destructor needed 
    // if base pointer that points to a derived object is ever deleted
    virtual ~Item_base() { } 
private:
    std::string isbn;   // identifier for the item
protected:
    double price;      // normal, undiscounted price

};

class Sales_item;

bool compare(const Sales_item &lhs, const Sales_item &rhs);

// discount kicks in when a specified number of copies of same book are sold
// the discount is expressed as a fraction used to reduce the normal price
//保存折扣率和购买数量的类  
//它有两个派生类,实现两种折扣模式 
//只要超过了预定的数量就都有折扣。
class Bulk_item : public Item_base 
{
public:
	//卖多少书和折扣率绑定
    std::pair<size_t, double> discount_policy() const
        { return std::make_pair(min_qty, discount); }
    // other members as before
    Bulk_item* clone() const 
        { return new Bulk_item(*this); }
	//两个构造函数
    Bulk_item(): min_qty(0), discount(0.0) { }
    Bulk_item(const std::string& book, double sales_price, 
              std::size_t qty = 0, double disc_rate = 0.0):
                 Item_base(book, sales_price), 
                 min_qty(qty), discount(disc_rate) { }

    // redefines base version so as to implement bulk purchase discount policy
	//重定义折扣价钱
    double net_price(std::size_t) const;
private:
    std::size_t min_qty;   // minimum purchase for discount to apply享受折扣最少买的书
    double discount;       // fractional discount to apply折扣率
};

// discount (a fraction off list) for only a specified number of copies, 
// additional copies sold at standard price
//超出部分才有折扣
class Lim_item : public Item_base 
{
public:
    Lim_item(const std::string& book = "", 
             double sales_price = 0.0,
             std::size_t qty = 0, double disc_rate = 0.0):
                 Item_base(book, sales_price), 
                 max_qty(qty), discount(disc_rate) { }

 // redefines base version so as to implement<实现> limited discount policy《折扣政策》
    double net_price(std::size_t) const;
private:
    std::size_t max_qty;   // maximum number sold at discount最大折扣
    double discount;       // fractional discount to apply折扣分数
public:
    Lim_item* clone() const { return new Lim_item(*this); }
    std::pair<size_t, double> discount_policy() const
        { return std::make_pair(max_qty, discount); }
};

// use counted handle class for the Item_base hierarchy 《继承层次结构》
//定义一个句柄类里管理这个继承层次中的基类或者派生类对象:
class Sales_item 
{
friend class Basket;
public:
    // default constructor: unbound handle
	//默认构造函数,不与任何对象关联,初始化指针为0  和 计数器为1
    Sales_item(): p(0), use(new std::size_t(1)) { }

    // attaches a handle to a copy of the Item_base object
    Sales_item(const Item_base&); 

    // copy control members to manage the use count and pointers
    Sales_item(const Sales_item &i): 
                      p(i.p), use(i.use) 
	         { ++*use; }

    ~Sales_item() { decr_use(); }

    Sales_item& operator=(const Sales_item&);

    // member access operators
    const Item_base *operator->() const 
		{
		   if (p) 
			   return p; 
           else 
			   throw std::logic_error("unbound Sales_item"); 
		}
    const Item_base &operator*() const { 
		   if (p)  
			   return *p; 
           else 
			   throw std::logic_error("unbound Sales_item"); 
		}
private:
    Item_base *p;           // pointer to shared item绑定到Item_base
	                      //执行Item_base的操作。
	                     //指向基类的指针,也可以用来指向派生类  
    std::size_t *use;     // pointer to shared use count
	                    //指向引用计数 

    // called by both destructor and assignment operator to free pointers
    void decr_use() 
         { if (--*use == 0) 
		      { 
			       delete p; 
				   delete use; 
		      } 
		 }
};

// holds items being purchased
class Basket 
{
    // type of the comparison function used to order the multiset
    typedef bool (*Comp)(const Sales_item&, const Sales_item&);
public:
    // make it easier to type the type of our set
    typedef std::multiset<Sales_item, Comp> set_type;

    // typedefs modeled after corresponding container types
    typedef set_type::size_type size_type;
    typedef set_type::const_iterator const_iter;

    void display(std::ostream&) const;

    // workaround MS compiler bug: must explicitly pass function address
	//默认构造函数,将比较函数确定为compare  
    Basket(): items(&compare) { }  // initialze the comparator 
	//容器内添加对象
    void add_item(const Sales_item &item) 
                        { items.insert(item); }
	//交易次数
    size_type size(const Sales_item &i) const
                         { return items.count(i); }
	//所欲的交易的钱数
    double total() const;  // sum of net prices for all items in the basket
private:
    std::multiset<Sales_item, Comp> items;
};

inline
Sales_item::Sales_item(const Item_base &item):
            p(item.clone()), use(new std::size_t(1)) { }

// compare defines item ordering for the multiset in Basket
inline bool 
compare(const Sales_item &lhs, const Sales_item &rhs) 
{
    return lhs->book() < rhs->book(); 
} 
#endif

源文件cpp

#include "Basket.h"
#include <algorithm>
using std::multiset; using std::map; using std::pair; using std::size_t;
using std::string; using std::ostream; using std::endl; using std::min;
using std::cout;

// debugging routine to check contents in a Basket
void Basket::display(ostream &os) const
{
    os << "Basket size: " << items.size() << endl;

    // print each distinct isbn in the Basket along with
    // count of how many copies are ordered and what their price will be
    // upper_bound returns an iterator to the next item in the set
    for (const_iter next_item = items.begin(); next_item != items.end();
                  next_item = items.upper_bound(*next_item))
    {
        // we know there's at least one element with this key in the Basket
        os << (*next_item)->book() << " occurs " 
           << items.count(*next_item) << " times" 
           << " for a price of " 
           << (*next_item)->net_price(items.count(*next_item)) 
           << endl;
    }
}

void print_total(ostream &, const Item_base&, size_t);

// calculate and print price for given number of copies, applying any discounts 
void print_total(ostream &os, 
                 const Item_base &item, size_t n)
{
    os << "ISBN: " << item.book() // calls Item_base::book
       << "\tnumber sold: " << n << "\ttotal price: "
       // virtual call: which version of net_price to call is resolved at run time
       << item.net_price(n) << endl;
}


double Basket::total() const
{
    double sum = 0.0;    // holds the running total 

	//首先是循环的遍历并不是使用iter++来完成的,而是使用iter = items.upper_bound(*iter)。对于multiset,upper_bound返回的是指向某一个键的最后一个元素的下一个位置,这样就可以一次处理同一本书。当然,这里的有一个前提,就是对于同一本书,它的折扣策略、折扣率以及达到折扣所满足的数量是一致的。
    for (const_iter iter = items.begin(); 
                    iter != items.end();
                    iter = items.upper_bound(*iter))
//iter解引获得的是Sales_item对象,利用定义的箭头操作符可以访问基类或者派生类的net_price函数,这个函数的派生类版本需要一个表明有多少本书才打折的实参,这个实参通过调用关联容器的count调用获得。
//(*iter)表示一个键值
    {
        // we know there's at least one element with this key in the Basket
        print_total(cout, *(iter->p), items.count(*iter));//count(*iter)几本书
        // virtual call to net_price applies appropriate discounts, if any
        sum += (*iter)->net_price(items.count(*iter));//count是相同的键值的个数作为参数
    }
    return sum;
}

// use-counted assignment operator; use is a pointer to a shared use count
Sales_item& Sales_item::operator=(const Sales_item &rhs)
{
    //引用计数+1
    ++*rhs.use;
	//删除原来的指针
    decr_use();
	//将指针指向右操作数 
	p = rhs.p;
	//复制右操作数的引用计数 
    use = rhs.use;
	//返回左操作数的引用
    return *this;
}

// if specified number of items are purchased, use discounted price 
double Bulk_item::net_price(size_t cnt) const
{
    if (cnt >= min_qty)
        return cnt * (1 - discount) * price;
    else
        return cnt * price;
}

// use discounted price for up to a specified number of items
// additional items priced at normal, undiscounted price
double Lim_item::net_price(size_t cnt) const
{
    size_t discounted = min(cnt, max_qty);
    size_t undiscounted = cnt - discounted;
    return discounted * (1 - discount) * price 
           + undiscounted * price;
}s) 
{
    return lhs->book() < rhs->book(); 
}

main函数

#include "Basket.h"
#include <iostream>
using std::cout; using std::endl;

int main()
{
	Sales_item item1(Item_base("123", 45));
	Sales_item item2(Bulk_item("345", 45, 3, .15));
	Sales_item item3(Bulk_item("678", 55, 5, .25));
	Sales_item item4(Lim_item("abc", 35, 2, .10));
	Sales_item item5(Item_base("def", 35));

	Basket sale;
	sale.add_item(item1);
cout << "added first item" << endl;
	
	sale.add_item(item1);
	sale.add_item(item2);
	sale.add_item(item2);
	sale.add_item(item2);
	sale.add_item(item2);
	sale.add_item(item2);
	sale.add_item(item1);
	sale.add_item(item1);
	sale.add_item(item2);
	sale.add_item(item2);
	sale.add_item(item2);
	sale.add_item(item3);
	sale.add_item(item3);
	sale.add_item(item3);
	sale.add_item(item3);
	sale.add_item(item3);
	sale.add_item(item3);
	sale.add_item(item3);
	sale.add_item(item3);
	sale.add_item(item4);
	sale.add_item(item4);
	sale.add_item(item4);
	sale.add_item(item4);
	sale.add_item(item4);
	sale.add_item(item4);
	sale.add_item(item5);
	sale.add_item(item5);
cout << "added last item" << endl;

	sale.display(cout);
	cout << sale.total() << endl;
{
	// arguments are the isbn, price, minimum quantity, and discount
	Bulk_item bulk("0-201-82470-1", 50, 5, .19);
	Basket sale;
	sale.add_item(Bulk_item("0-201-82470-1", 50, 5, .19));
	sale.add_item(Bulk_item("0-201-82470-1", 50, 5, .19));
	sale.add_item(Bulk_item("0-201-82470-1", 50, 5, .19));
	sale.add_item(Bulk_item("0-201-82470-1", 50, 5, .19));
	sale.add_item(Bulk_item("0-201-82470-1", 50, 5, .19));
	sale.add_item(Lim_item("0-201-54848-8", 35, 2, .10));
	sale.add_item(Lim_item("0-201-54848-8", 35, 2, .10));
	sale.add_item(Lim_item("0-201-54848-8", 35, 2, .10));
	double total = sale.total();
	cout << "Total Sale: " << total << endl;
}
}



 

你可能感兴趣的:(编程,C++,String,iterator,destructor,Pointers)