首页 > 代码库 > 智能指针与句柄类(四)
智能指针与句柄类(四)
当我们希望使用容器来保存继承体系中的对象时,容器用于继承体系中的类型会有影响:派生类对象复制到基类对象时,派生类对象将被切掉。那么解决这一问题的方法通常是使用容器保存基类对象的指针,这些指针实际指向的是程序运行时动态分配的派生类对象,用户必须保证在容器析构前调用delete来释放动态分配的对象,如下例:
1 class Base 2 { 3 public: 4 virtual void action() = 0; 5 }; 6 class Derived1 : public Base 7 {...}; 8 class Derived2 : public Base 9 {...};10 class Derived3 : public Base11 {...};12 13 void fun()14 {15 vector<Base*> v;16 17 v.push_back(new Derived1);18 v.push_back(new Derived2);19 v.push_back(new Derived3);20 21 for(int i=0; i!=v.size(); i++)22 v[i]->action();23 24 for(int i=0; i!=v.size(); i++)25 delete v[i];26 27 return;28 }
我们可以使容器保存之前定义的Handle类对象,Handle类对象管理继承层次中的对象指针,对其生命周期进行控制,而不用再结束时手动释放动态分配的内存。
1 vector<Handle<Base> > vh;2 vh.push_back(new Derived1);3 vh.push_back(new Derived2);4 vh.push_back(new Derived3);5 6 for(int i=0; i!=vh.size(); i++)7 vh[i]->action();
在《C++ Primer》中,容器类保存句柄类,句柄类封装之前定义的Handle类对象,并通过Handle类对象对指针进行管理与计数,控制复制、赋值以及指针的释放。以<<C++Primer>>中的继承层次为例:
1 class Item_Base 2 { 3 public: 4 //...constructor... 5 virtual Item_Base* clone()const {return new Item_Base(*this)} 6 7 virtual double net_price(size_t) const; 8 virtual ~Item_Base(){} 9 private:10 string isbn;11 protected:12 double price;13 };14 15 class Bulk_item : public Item_Base16 {17 public:18 //...constructor...19 virtual Bulk_item* clone()const {return new Bulk_item(*this)}20 21 double net_price(size_t) const;22 private:23 size_t min_qty;24 double discount;25 };26 27 class Disc_item : public Item_Base28 {29 public:30 //...constructor...31 virtual Disc_item* clone()const {return new Disc_item(*this)}32 33 double net_price(size_t)const;34 private:35 size_t quantity;36 };
clone虚函数进行复制,对于派生类的返回类型必须与基类实例的返回类型完全匹配的要求,有一个例外:如果虚函数的基类实例返回类类型的引用或指针,则该虚函数的派生类实例可以返回基类实例返回的类型的派生类(或者是类类型的指针或引用)。有了clone函数的定义,对于句柄类的构造函数就很简单了:
1 class Sales_item 2 { 3 public: 4 Sales_item():h(){} 5 Sales_item(const Item_Base &item):h(item.clone()) {} 6 const Item_Base & operator*() const{return *h} 7 const Item_Base * operator->() const {return h.operator->} 8 private: 9 Handle<Item_Base> h;10 };
这种方式进行处理时,客户代码段甚至不需要进行new操作,所有的分配和释放都在Sales_item内部完成。
1 vector<Sales_item> vItem;2 vItem.push_back(Disc_Item());3 vItem.push_back(Bulk_item());
智能指针与句柄类(四)
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。