• 句柄类与继承


     1 /**
     2  * C++ 面向对象编程的一个颇具讽刺意味的地方是:不能使用对象支持面向对象编程,
     3  *相反,必须使用指针或引用,例如:
     4  */
     5 void get_prices(Item_base object, const Item_base *pointer, const Item_base &reference)
     6 {
     7     //下边的两个调用在运行时进行动态绑定
     8     cout << pointer->net_price(1) << endl;
     9     cout << reference.net_price(1) << endl;
    10     
    11     //下边的调用无论是基类还是子类都调用基类的成员函数
    12     cout << object.net_price(1) << endl;
    13 }

     

    指针型句柄练习:

     1 //Basket.h
     2 #ifndef BASKET_H
     3 #define BASKET_H
     4 
     5 #include "Sales_item.h"
     6 #include <set>
     7 
     8 inline bool compare(const Sales_item &lhs, const Sales_item &rhs)
     9 {
    10     return lhs->book() < rhs->book();
    11 }
    12 
    13 class Basket
    14 {
    15     //用于multiset元素排序的比较函数的类型---Comp是函数指针,指向的函数带有两个Sales_item类型的参数
    16     typedef bool (*Comp)(const Sales_item&, const Sales_item&);
    17 public:
    18     //multiset成员的类型
    19     typedef std::multiset<Sales_item, Comp> set_type;
    20     //类型别名
    21     typedef set_type::size_type size_type;
    22     typedef set_type::const_iterator const_itor;
    23     
    24     Basket() : items(compare) {} //初始化比较器
    25     
    26     void add_item(const Sales_item &item)
    27     {
    28         items.insert(item);
    29     }
    30     
    31     size_type size(const Sales_item &i) const
    32     {
    33         return items.count(i);
    34     }
    35     
    36     double total() const;  // 返回购物篮中所有物品的总价格
    37 private:
    38     std::multiset<Sales_item, Comp> items;
    39 };
    40 
    41 #endif
     1 //定义compare函数和Basket类的实现文件如下:
     2 //Basket.cpp
     3 
     4 #include "Basket.h"
     5 
     6 double Basket::total() const
     7 {
     8     double sum = 0.0;    // holds the running total
     9     
    10     // 找到具有相同 ISBN 的每一组物品,根据其总数计算价格,itor指向 ISBN 相同的每一组中的第一个元素
    11     //    upper_bound 指向具有不同 ISBN 的下一个元素
    12     for(const_itor itor = items.begin(); itor != items.end(); itor = items.upper_bound(*itor))
    13     {
    14         sum += (*itor)->net_price(items.count(*itor));
    15     }
    16     return sum;
    17 }
     1 // 使用 Basket 类管理销售
     2 #include "Basket.h"
     3 #include "Sales_item.h"
     4 #include <iostream>
     5 using namespace std;
     6 
     7 int main()
     8 {
     9     Basket basket;
    10     Sales_item item1(Bulk_item("7-115-14554-7", 99, 20, 0.2));
    11     Sales_item item2(Item_base("7-115-14554-8", 39));
    12     Sales_item item3(Lds_item("7-115-14554-9", 50, 200, 0.2));
    13     Sales_item item4(Bulk_item("7-115-14554-7", 99, 20, 0.2));
    14     
    15     basket.add_item(item1);
    16     basket.add_item(item2);
    17     basket.add_item(item3);
    18     basket.add_item(item4);
    19     
    20     cout << basket.total() << endl;
    21     
    22     return 0;
    23 }
      1 // Item.h
      2 //  定义Item_base类层次的头文件
      3 
      4 #ifndef ITEM_H
      5 #define ITEM_H
      6 #include <string>
      7 
      8 using namespace std;
      9 
     10 // 不使用折扣策略的基类
     11 class Item_base
     12 {
     13 public:
     14     Item_base(const std::string &book = "", double sales_price = 0.0) :
     15         isbn(book), price(sales_price){}
     16     
     17     std::string book() const
     18     {
     19         return isbn;
     20     }
     21     // 返回特定购书量的总价格---派生类将重载该函数以应用不同的折扣策略
     22     virtual double net_price(size_t n) const
     23     {
     24         return n * price;
     25     }
     26     
     27     virtual Item_base* clone() const
     28     {
     29         return new Item_base(*this);
     30     }
     31     
     32     virtual ~Item_base() {}
     33 private:
     34     std::string isbn;
     35 protected:
     36     double price;
     37 };
     38 
     39 //保存折扣率和可实行折扣策略的数量---派生类将使用这些数据实行定价策略
     40 class Disc_item : public Item_base
     41 {
     42 public:
     43     Disc_item(const std::string& book = "", double sales_price = 0.0,
     44               size_t qty = 0, double disc_rate = 0.0) :
     45                    Item_base(book, sales_price), quantity(qty), discount(disc_rate) {}
     46                    
     47     double net_price(size_t) const = 0; //纯虚函数---该函数为后代类型提供了可以覆盖的接口,
     48                 //但是这个类中的版本决不会调用,重要的是,用户将不能创建Disc_item类型的对象
     49     
     50     std::pair<size_t, double> discount_policy() const
     51     {
     52         return std::make_pair(quantity, discount);
     53     }
     54 protected:
     55     size_t quantity;  //可实行折扣策略的购买量
     56     double discount;  // 折扣率
     57 };
     58 
     59 // 批量购买折扣类
     60 class Bulk_item : public Disc_item
     61 {
     62 public:
     63     Bulk_item(const std::string& book = "", double sales_price = 0.0,
     64               size_t qty = 0, double disc_rate = 0.0) :
     65                     Disc_item(book, sales_price, qty, disc_rate) {}
     66                     
     67     // 重定义基类版本以实行批量购买折扣策略:若购书量高于下限,则使用折扣价格
     68     double net_price(size_t cnt) const
     69     {
     70         if(cnt >= quantity)
     71             return cnt * (1-discount) * price;
     72         else
     73             return cnt * price;
     74     }
     75     
     76     virtual Bulk_item* clone() const
     77     {
     78         return new Bulk_item(*this);
     79     }
     80 };
     81 
     82 //有限折扣类
     83 class Lds_item : public Disc_item
     84 {
     85 public:
     86     // 构造函数
     87     Lds_item(const std::string& book = "", double sales_price = 0.0,
     88               size_t qty = 0, double disc_rate = 0.0) :
     89                     Disc_item(book, sales_price, qty, disc_rate) {}
     90                     
     91     // 重定义基类版本以实现有限折扣策略---对低于上限的购书量使用折扣价格
     92     double net_price(size_t cnt) const
     93     {
     94         if(cnt <= quantity)
     95             return cnt * (1 - discount) * price;
     96         else
     97             return cnt * price - quantity * discount * price;
     98     }
     99     
    100     virtual Lds_item* clone() const
    101     {
    102         return new Lds_item(*this);
    103     }
    104 };
    105 
    106 #endif
     1 // Sales_item.h---Sales_item 类的头文件
     2 
     3 #ifndef SALESITEM_H
     4 #define SALESITEM_H
     5 #include "Item.h"
     6 
     7 // 用于Item_base 层次的使用计数式句柄类
     8 class Sales_item
     9 {
    10 public:
    11     // 默认构造函数:创建未绑定的句柄
    12     Sales_item() : p(0), use(new std::size_t(1)) { }
    13     
    14     // 将创建绑定到Item_base对象副本的句柄
    15     Sales_item(const Item_base& item) : p(item.clone()), use(new std::size_t(1)) { }
    16     
    17     // 复制控制成员管理使用计数和指针
    18     Sales_item(const Sales_item &i) : p(i.p), use(i.use) { ++*use; };
    19     ~Sales_item() { decr_use(); }
    20     Sales_item& operator = (const Sales_item);
    21     
    22     //成员访问操作符
    23     const Item_base *operator->() const
    24     {
    25         if(p)
    26             return p;
    27         else
    28             throw std::logic_error("unbound Sales_item");
    29     }
    30     const Item_base &operator*() const
    31     {
    32         if(p)
    33             return *p;
    34         else
    35             throw std::logic_error("unbound Sales_item");
    36     }
    37 private:
    38     Item_base *p;    //指向共享Item_base对象的指针
    39     std::size_t *use;  //指向共享使用计数的指针
    40     
    41     // 为析构函数和赋值操作符所用的辅助函数
    42     void decr_use()
    43     {
    44         if(--*use == 0)
    45         {
    46             delete p;
    47             delete use;
    48         }
    49     }
    50 };
    51 #endif
     1 // Sales_item.cpp---Sales_item 类的实现文件(源文件)
     2 #include "Sales_item.h"
     3 
     4 Sales_item& Sales_item::operator = (const Sales_item &rhs)
     5 {
     6     ++*use;
     7     decr_use();
     8     p = rhs.p;
     9     use = rhs.use;
    10     return *this;
    11 }
  • 相关阅读:
    Object.defineProperty实现数据绑定
    trigger回调方法的实现
    window.print()打印页面指定内容(使用iframe保证原页面不失效)
    Visual Studio Code 快捷键大全(Windows)
    个人博客-逐梦博客,宋
    Vue.js项目在apache服务器部署后,刷新404的问题
    阿里云ECS服务器Ubuntu配置MySQL远程访问
    最全面的css布局
    js中数组常用方法总结
    PHP环境搭建
  • 原文地址:https://www.cnblogs.com/dongsheng/p/3342073.html
Copyright © 2020-2023  润新知