c++面向对象编程的一个例子(书店)

来源:互联网 发布:社工数据库 编辑:程序博客网 时间:2024/05/01 20:14

本例子是c++ primer书中第15章面向对象编程的一个贯穿全章的例子:

#include <iostream>#include <stdexcept>#include <set>using namespace std;/*Item_base类定义了book和net_price函数并且需要存储每本书的ISBN和标准价格*/class Item_base {    public:        Item_base(const string &name = "", double normal_price = 0.0):ISBN(name), price(normal_price) {}        string book() const {return ISBN;}        virtual double net_price(size_t n) const{            return n*price;        }        virtual Item_base* clone() const {            return new Item_base(*this);//默认调用拷贝构造函数        }        //调试信息,方便以后调试        virtual void debug(ostream &os = cout) const {            os << ISBN << "\t" << price << endl;        }        virtual ~Item_base() {}    private:        string ISBN;    protected:        double price;};//重构class Disc_item:public Item_base {    public:        Disc_item(const string &name = "", double normal_price = 0.0, size_t qty = 0, double rate = 0.0) :            Item_base(name, normal_price), min_qty(qty), discount(rate) {}        double net_price(size_t) const = 0;//纯虚函数        /*virtual Disc_item* clone() const {            return new Disc_item(*this);        }*/        virtual void debug(ostream &os = cout) const {            Item_base::debug(os);            os << min_qty << "\t" << discount << endl;        }    protected:        size_t min_qty;        double discount;};class Bulk_item:public Disc_item {    public:        Bulk_item(const string &name = "", double normal_price = 0.0, size_t qty = 0, double rate = 0.0) :            Disc_item(name, normal_price, qty, rate) {}        double net_price(size_t t) const {//派生类型必须对纯虚函数进行重新定义            double sum = 0.0;            if(t > min_qty) sum = t*discount*price;            else sum = t*price;            return sum;        }        virtual Bulk_item* clone() const {            return new Bulk_item(*this);        }        //virtual ~Bulk_item() {}};//句柄类class Sales_item {    public:        Sales_item():ib(0),use(new size_t(1)){}        Sales_item(Item_base &i):ib(i.clone()), use(new size_t(1)) {}        //拷贝构造函数        Sales_item(const Sales_item &si):ib(si.ib), use(si.use) {++*use;}        //重载赋值操作符,考虑自身赋值        Sales_item& operator=(const Sales_item &si) {            ++*(si.use);//只能放在这个位置。不能和下面的语句互换。这样可以处理自身赋值的情况            desc_use();            ib = si.ib;            use = si.use;            return *this;        }        ~Sales_item() {desc_use();}        //重载成员访问操作符        const Item_base& operator*() const {            if(ib) return *ib;            else throw logic_error("unbound Sales_item");        }        const Item_base* operator->() const {            if(ib) return ib;            else throw logic_error("unbound Sales_item");        }    private:        Item_base *ib;        size_t *use;        inline void desc_use() {            if(0 == --*use) {delete ib; delete use;}        }};//按照书名进行排序inline bool compare(const Sales_item &lsi, const Sales_item &rsi) {    return lsi->book() < rsi->book();}class Basket {    public:        typedef bool (*Comp)(const Sales_item&, const Sales_item&);//使用Comp做为函数指针的同义词,简化代码        Basket():items(compare) {}//构造函数,用compare函数初始化        void add_item(const Sales_item& si) {items.insert(si);}        int size(const Sales_item& si) {return items.count(si);}        double total() const;    private:        multiset<Sales_item, Comp> items;};//返回购物蓝中所有物品的价格double Basket::total() const {    double sum = 0.0;    for(multiset<Sales_item, Comp>::iterator iter = items.begin(); iter != items.end(); iter = items.upper_bound(*iter))        sum += (*iter)->net_price(items.count(*iter));    return sum;}int main(){    Basket basket;    //Sales_item item1(Bulk_item("2013-8-12",15.1,3,0.2));    Item_base ib("2013-8-11",20.2);    Bulk_item bi("2013-8-12",15.1,3,0.2);    Sales_item item1(bi);    Sales_item item2(ib);    //Sales_item item2(Item_base("2013-8-11",20.2));    //Sales_item item3(Disc_item("2013-8-12",15.1,3,0.2));    basket.add_item(item1);    basket.add_item(item2);    //basket.add_item(item3);    cout << basket.total() << endl;    return 0;}
总结:本例子涉及到很多的知识点。比如类的设计(用到了重构),句柄类,继承与多态等。

原创粉丝点击