《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;
}
}



 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
推荐的C++面向对象编程的书籍有以下几本: 1. 《C++ Primer》:这本书是C++编程的经典教材之一,全面介绍了C++的基本知识和面向对象编程的概念和技巧。\[1\] 2. 《面向对象程序设计》(作者:杜茂康):这本书详细介绍了C++面向对象编程的内容,包括类、对象、继承、多态性、虚函数、重载等。同时还介绍了C++的一些高级特性和应用,如I/O流类库、模板与STL、C++ Windows程序的结构等。\[2\] 3. 《C++面向对象程序设计》(作者:刘伟):这本书系统地介绍了C++面向对象编程的基本概念和方法,包括封装、继承、多态等。同时还介绍了C++的一些高级特性和应用,如操作符重载、面向接口编程和模板等。\[3\] 这些书籍都是经典的C++面向对象编程教材,适合不同层次的读者,无论是初学者还是有一定编程经验的人都可以从中获得丰富的知识和技巧。 #### 引用[.reference_title] - *1* *3* [清华大学出版社-图书详情-《C++面向对象程序设计(第2版)》](https://blog.csdn.net/weixin_39530269/article/details/117094822)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^control_2,239^v3^insert_chatgpt"}} ] [.reference_item] - *2* [发现一本C++面向对象编程的好书](https://blog.csdn.net/PerfeyCui/article/details/122726546)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^control_2,239^v3^insert_chatgpt"}} ] [.reference_item] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值