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 }