C++ 中的句柄类

C++中面向对象编程的一个颇具讽刺意味的地方是,不能使用对象支持面向对象编程,相反必须使用指针或者引用。C++中的多态性:动态绑定必须使用基类的指针或者引用调用虚函数来进行。 或者说STL容器来存储继承层次的对象,派生类对象复制给基类对象会被截断为基类对象,不能将基类对象复制给派生类对象,STL容器最好是存储对象的指针。所以具有继承层次的对象,在C++中程序中更多的使用对象的指针

                但使用指针又会加重用户的负担,特别是类中存在指针成员时,因为类的复制控制,很容易导致以下问题:

1.   多个类的对象中的指针是指针的同一块内存,存在一个修改,全部受影响的情况,容易造成程序的逻辑错误;

2. 很可能在某处删除了指针对象,而其他地方认为指针对象还存在,继续访问指针指向的对象,访问悬空指针的结果很随机,容易造成严重的运行时错误

                而智能指针是C++中常见的使用指针方式,可以有效的解决悬垂指针的问题。句柄类就是封装了继承层次类的智能指针。句柄类存储和管理基类指针。指针说指对象的类型可以变化,它既可以指向基类类型对象又可以指向派生类型对象,用户通过句柄类访问继承层次操作。句柄的用户可以获得动态行为但无须操心指针的管理。

                包装了继承层次的句柄有两个重要的设计考虑因素:

1.      必须确定对复制控制怎么处理,句柄通常表现的像一个智能指针或者像一个值一样

2.      句柄类决定句柄接口还是不是屏蔽继承层次,如果不屏蔽继承层次,用户必须了解和使用基本层次中的对象。


#include <iostream>
#include <iterator>
#include <algorithm>
#include <fstream>
#include <list>
#include <string>
#include <vector>
#include <set>
#include<utility>
#include<functional>
#include<stdexcept>


//base class
class Item_base
{

friend std::ostream& operator<<(std::ostream &, Item_base &);

public:
    Item_base(const std::string& book="",double sale_price=0.0):isbn(book),price(sale_price) {}

    std::string book() const { return isbn;}

    virtual Item_base* clone() const
    {
        return new Item_base(*this);
    }

    virtual double net_price(std::size_t n) const
    {
        return price*n;
    }

    //debug function controlled by flag parameter
    virtual void debug1(bool flag) const
    {
        if(flag)
        std::cout<<"ISBN: "<<isbn<<std::endl
                <<"Price: "<<price<<std::endl;
    }


    //debug function controlled by flag member
    virtual void debug2() const
    {
        if(flag)
        std::cout<<"ISBN: "<<isbn<<std::endl
                <<"Price: "<<price<<std::endl;

    }

    virtual ~Item_base() {}

protected:
    double price;                // price of a book
    bool flag;
private:
    std::string isbn;         // isbn  of a book

};

std::ostream& operator<<(std::ostream &  os,Item_base& ib)
{
    os<<"\tUsing operator<<(std::ostream &,Item_base&);"<<std::endl
       <<"\tVisit Item_base's book():\t"<<ib.isbn<<std::endl
       <<"\tVisit Item_base's net_price():"
       <<"3 "<<ib.book()<<" , the price is:\t"
       <<ib.net_price(3)<<std::endl;
    return os;
}



//derived class
class Bult_Item :public Item_base
{
friend std::ostream & operator<<(std::ostream & ,Bult_Item &);

public:
    Bult_Item(const std::string& book="",double sale_price=0.0,std::size_t qty=0,double disc=0.0):Item_base(book,sale_price),min_qty(qty),discount(disc) {}

    Bult_Item* clone() const
    {
        return new Bult_Item(*this);
    }

    double net_price(std::size_t cnt) const
    {
        if(cnt > min_qty)
            return cnt*(1-discount)*price;

    }

    void debug1(bool flag) const
    {
        if(flag)
        std::cout<<"ISBN: "<<book()<<std::endl
                 <<"PriceL "<<price<<std::endl
                 <<"Min_quantiry: "<<min_qty<<std::endl
                 <<"Discount Rate: "<<discount<<std::endl;
    }


    void debug2() const
    {
        if(flag)
        std::cout<<"ISBN: "<<book()<<std::endl
                 <<"PriceL "<<price<<std::endl
                 <<"Min_quantiry: "<<min_qty<<std::endl
                 <<"Discount Rate: "<<discount<<std::endl;

    }

    ~Bult_Item() {}

private:
    std::size_t min_qty;                // min quantity of books to have a discount
    double discount;                 //discount rate
};


std::ostream & operator<<(std::ostream &  os,Bult_Item & bi)
{
    os<<"\tUsing operator<<(std::ostream &,Bulk_Item);"<<std::endl
       <<"\tVisit Item_base's book():\t"<<bi.book()<<std::endl
       <<"\tVisit Item_base's net_price():"
       <<"5 "<<bi.book()<<" , the price is:\t"
       <<bi.net_price(5)<<std::endl;
    return os;

}



//handle class 
class Sales_item
{
public:
    //default constructor:unbound handle
    Sales_item():p(0),use( new std::size_t(1)) {}
    //attaches a handle to copy of the Item_base object
    Sales_item(const Item_base & item):p(item.clone()),use(new std::size_t(1)) {}

    //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& operator=(const Sales_item&);


    ~Sales_item() { decr_use();}

    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
    std::size_t * use ;   // pointer to a shared use count( reference count);
    void decr_use()
    {
        if(--*use == 0)
        {
            delete p;
            delete use;
        }
    }
};




Sales_item& Sales_item::operator=(const Sales_item& rhs)
{
     ++*rhs.use;
     decr_use();
     p = rhs.p;
     use =  rhs.use;
     return * this;
}


//compare function of Sales_Item for multiset to use
inline bool compare(const Sales_item& rh1,const Sales_item& rh2)
{
    return rh1->book() < rh2->book() ;

}




//really class used in real business
class  Basket
{
    typedef bool (*Comp) (const Sales_item&,const Sales_item&);

public:
    typedef std::multiset<Sales_item,Comp> set_type;
    typedef set_type::size_type size_type;
    typedef set_type::const_iterator const_iter;

    //constructor
    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:
    std::multiset<Sales_item,Comp> items;


};


double Basket::total() const
{
    double sum = 0.0;

    for(const_iter i = items.begin() ;  i != items.end() ; i = items.upper_bound(*i))
    {
        sum += (*i)->net_price(items.count(*i));
    }


    return sum;

}


//test code
int main()
{

    return 0;

}



示例代码地址:

https://github.com/QiJunHu/learningRecord/blob/master/learningC%2B%2B/learningHandleClass.cpp

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值