C ++ Primer study note _ 72 _ object-oriented programming -- handle class and inheritance [continued]

Source: Internet
Author: User

Object-Oriented Programming-handle class and inheritance [continued]



Iii. Use of handles

You can use the Sales_item object to write bookstore applications more easily. The Code does not need to manage the pointer of the Item_base object, but can still obtain the virtual behavior of calling through the Sales_item object.



1. Compare two Sales_item objects

Before writing a function to calculate the total sales volume, you must define a method for comparing Sales_item objects.To useSales_itemKeyword used as the associated container,Must be able to compare them. The associated container uses the less than operator of the keyword type by default. However, if the less than operator is defined for Sales_item, its meaning is unknown;

Fortunately, the associated container enables us to specify a function [or function object] as a comparison function. In addition, you must provide a comparison function when defining container objects.

Define a function to compare the Sales_item object:

inline boolcompare(const Sales_item &lsh,const Sales_item &rhs){    return lsh -> book() < rhs -> book();}

This function uses the-> operator of Sales_item. This operator returns the pointer to the Item_base object, which is used to obtain and run the Member's book operation, and this member returns ISBN.



2. Use tapeComparatorContainer

For a comparison function, it must be stored as a part of the container, and any operation to add or search for elements in the container must use a comparison function.

To work effectively, the associated container needs to be used for each operationSame comparison Function. However, it is unreasonable to expect users to remember comparison functions every time, especially,No wayCheckUse the same comparison function for each call. Therefore, it makes sense for containers to remember comparison functions. By storing the comparator in a container object, you can ensure that each operation of the comparison element is performed in a consistent manner.

To store the comparator, it needs to know the comparator type. The parameter type does not need to be exactly the same as that of key_type. It should be allowed to convert any type of parameter to key_type.

Therefore, to use the comparison function of Sales_itemRequiredSpecify the comparator type. In our example, the comparator type is a function that accepts two constSales_item references and returns the bool value.

    typedef bool (*Comp)(const Sales_item &,const Sales_item &); 

Define Comp as the synonym of the function type pointer. The function type matches the comparison function we want to use to compare the Sales_item object.

Next, you need to define multiset, save the objects of the Sales_item type, and use this Comp type in its comparison function.Each constructor of the associated container enables us to provide the name of the comparison function..

You can define the empty multiset using the compare function as follows:

    std::multiset
 
   items(compare);
 

In this definition,ItemsIsMultisetIt saves the Sales_item object and compares them with the Comp type objects. Multiset is empty -- we do not provide any elements, but we doProvidesCompareComparison Functions. When an element is added or searched in items, the multiset is sorted using the compare function.



3. containers and handles

We define a Basket class to track sales and calculate purchase prices:

class Basket{    typedef bool (*Comp)(const Sales_item &,const Sales_item &);public:    typedef multiset
 
   set_type;    typedef set_type::size_type size_type;    typedef set_type::const_iterator const_iter;    Basket():items(compare) {}    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;private:    multiset
  
    items;};
  
 

This class defines a constructor, that is, the Basket default constructor.This class requires its own default constructorComparePassed to CreationItemsMember'sMultisetConstructor.



4. Use a handle to execute virtual functions

The total function in the Basket class is used to return the price of all items in the Basket:

double Basket::total() const{    double sum = 0.0;    for (set_type::iterator iter = items.begin();            iter != items.end();            iter = items.upper_bound(*iter))    {        sum += (*iter) -> net_price(items.count(*iter));    }    return sum;}

The "increment" expression in the for loop is very interesting. Unlike reading the General loop of each element, we push the iter to the next key. Call the upper_bound function to skip all elements that match the current key. The upper_bound function calls an iterator that points to the next element of the last element that is the same as the iter key, that is, the iterator points to the end of the set or the next book. Test the new iter value. If it is equal to items. end (), The for loop is exceeded. Otherwise, the next book is processed.

We use the count member of multiset to determineHow many members have the same key?(That is, the same isbn), and use this number as the real parameter to call the net_price function.

The for loop body calls the net_price function. Reading this call requires some tips:

sum += (*iter) -> net_price(items.count(*iter)); 

Obtain the base Sales_item object from iter's unreferenced operation, and apply the heavy-duty arrow operator of the Sales_item class to the object. The operator returns the pointer of the base Item_base object associated with the handle, use the Item_base object pointer to call the net_price function and pass the count of books with the same isbn as the real parameter. Net_price is a virtual function, so the version of the called pricing function depends on the type of the basic Item_base object.


// P511 exercise 15.35 // 1 in item. h # ifndef ITEM_H_INCLUDED # define ITEM_H_INCLUDED # include
 
  
# Include
  
   
Class Item_base {public: Item_base (const std: string & book = "", double sales_price = 0.0): isbn (book), price (sales_price) {} std :: string book () const {return isbn;} virtual double net_price (std: size_t n) const {return price * n;} virtual Item_base * clone () const {return new Item_base (* this);} virtual ~ Item_base () {} private: std: string isbn; protected: double price;}; class Disc_item: public Item_base {public: Disc_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), quantity (qty ), discount (disc_rate) {} virtual double net_price (std: size_t) const = 0; std: pair
   
    
Discount_policy () const {return std: make_pair (quantity, discount);} protected: std: size_t quantity; double discount;}; class Bulk_item: public Disc_item {public: bulk_item (const std: string & book = "", double sales_price = 0.0, std: size_t qty = 0, double disc_rate = 0.0): Disc_item (book, sales_price, qty, disc_rate) {} virtual double net_price (std: size_t n) const {if (n> = quantity) {return n * (1-discount) * price ;} else {return n * price;} virtual Bulk_item * clone () const {return new Bulk_item (* this) ;}}; class Lds_item: public Disc_item {public: lds_item (const std: string & book = "", double sales_price = 0.0, std: size_t qty = 0, double disc_rate = 0.0): Disc_item (book, sales_price, qty, disc_rate) {} virtual double net_price (std: size_t n) const {if (n <= quantity) {return n * (1-discount) * price ;} else {return n * price-quantity * discount * price;} virtual Lds_item * clone () const {return new Lds_item (* this) ;}; # endif // ITEM_H_INCLUDED
   
  
 

//2 in sales_item.h#ifndef SALES_ITEM_H_INCLUDED#define SALES_ITEM_H_INCLUDED#include "item.h"#include 
 
  class Sales_item{public:    Sales_item():p(0),use(new std::size_t(1)) {}    Sales_item(const Item_base &rhs):        p(rhs.clone()),use(new std::size_t(1)) {}    Sales_item(const Sales_item &rhs):p(rhs.p),use(rhs.use)    {        ++ *use;    }    ~Sales_item()    {        decr_use();    }    Sales_item &operator=(const Sales_item &rhs);    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;    std::size_t *use;    void decr_use()    {        if (-- *use)        {            delete p;            delete use;        }    }};#endif // SALES_ITEM_H_INCLUDED
 

//3 in sales_item.cpp#include "sales_item.h"Sales_item &Sales_item::operator=(const Sales_item &rhs){    ++ * rhs.use;    decr_use();    p = rhs.p;    use = rhs.use;    return *this;}

//4 in basket.h#ifndef BASKET_H_INCLUDED#define BASKET_H_INCLUDED#include "sales_item.h"#include 
 
  inline boolcompare(const Sales_item &lhs,const Sales_item &rhs){    return lhs -> book() < rhs -> book();}class Basket{    typedef bool (*Comp)(const Sales_item &,const Sales_item &);public:    typedef std::multiset
  
    set_type;    typedef set_type::size_type size_type;    typedef set_type::const_iterator const_iter;    Basket():items(compare){}    void add_item(const Sales_item &item)    {        items.insert(item);    }    size_type size(const Sales_item &item) const    {        return items.count(item);    }    double total() const;private:    std::multiset
   
     items;};#endif // BASKET_H_INCLUDED
   
  
 

//5 in basket.cpp#include "basket.h"double Basket::total() const{    double sum = 0.0;    for (set_type::iterator iter = items.begin();            iter != items.end();            iter = items.upper_bound(*iter))    {        sum += (*iter) -> net_price(items.count(*iter));    }    return sum;}

//6 in main.cpp#include 
 
  #include "item.h"#include "basket.h"using namespace std;int main(){    Basket basket;    Sales_item item1(Bulk_item("7-115-14554-7",99,20,0.2));    Sales_item item2(Item_base("7-115-14554-7",39));    Sales_item item3(Lds_item("7-115-14554-7",50,200,0.2));    Sales_item item4(Bulk_item("7-115-14554-7",99,20,0.2));    basket.add_item(item1);    basket.add_item(item2);    basket.add_item(item3);    basket.add_item(item4);    cout << basket.total() << endl;}
 

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.