C++中智能指针应用例子

  在C++中的容器或是数组中保存具有集成关系的类的对象,会导致派生类对象被强制转换为基类的对象。这样就会导致派生类对象被切割。所以不能直接在容器中存储这样的对象。其中一种解决的办法是存储指向对象的指针。这样又会带来一种问题,我们拷贝容器内容或是堆栈上的对象被释放的时候会出现悬空的指针,重复释放一个地址,或者是堆上保留了多份的对象拷贝。这些情况带来的影响都是不断扩大的,以至于最终超出控制。所以常采取的方案是采用智能指针的方法(句柄的概念)。我们的句柄类中保存了对象的指针和引用的计数。这样一来,我们就可以采用智能指针来调用对象的操作。这种方法非常灵活,充分利用了C++的多态性。因为C++中的虚函数通过指针或是引用的时候才会体现出多态性。下面是C++ Primer中列举的一个例子。

 

#include "stdafx.h"
#include<iostream>
#include<string>
#include<vector>

class Sales_base
{
public:
 Sales_base(const std::string &nm=" ",double pr=0.0)
  :isbn(nm),price(pr){}
 Sales_base(const Sales_base &sb)
 {
  isbn=sb.isbn;
  price=sb.price;
 }
 virtual ~Sales_base(){}
 virtual double net_price(std::size_t n)const
 {
  return n*price;
 }
 virtual Sales_base *clone()const
 {
  return new Sales_base(*this);
 }
 const std::string &get_isbn()const
 {
  return isbn;
 }
protected:
 std::string isbn;
 double price;
};

class Bulk_item : public Sales_base
{
public:
 Bulk_item(const std::string &nm=" ",double pr=0.0,std::size_t min=0,double disc=0.0)
  :Sales_base(nm,pr),min_qty(min),discount(disc){}
 Bulk_item(const Bulk_item &bi)
  :Sales_base(bi)
 {
  min_qty=bi.min_qty;
  discount=bi.discount;
 }
 virtual ~Bulk_item(){}
 Bulk_item *clone()const
 {
  return new Bulk_item(*this);
 }
 double net_price(std::size_t n)const
 {
  if(n>=min_qty)
   return price*(1-discount)*n;
  else
   return price*n;
 }
protected:
 std::size_t min_qty;
 double discount;
};

class Sales_item
{
public:
 Sales_item()
  :p(0),used(new std::size_t(1)){}
 Sales_item(const Sales_item &si)
  :p(si.p),used(si.used){++*used;}
 Sales_item(const Sales_base &sb)
 {
  p=sb.clone();
  used=new std::size_t(1);
 }
 ~Sales_item(){decr_use();}
 Sales_item &operator=(const Sales_item &si);
 Sales_base *operator->()
 {
  if(p)
   return p;
  else
   throw std::logic_error("NULL Pointer");
 }
 Sales_base &operator*()
 {
  if(p)
   return *p;
  else
   throw std::logic_error("NULL Pointer");
 }
protected:
 Sales_base *p;
 std::size_t *used;
 void decr_use()
 {
  if(--*used==0)
  {
   delete p;
   delete used;
  }
 }
};

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


int _tmain(int argc, _TCHAR* argv[])
{
 std::vector<Sales_item> sv;
 sv.push_back(Sales_item(Sales_base("C++ Primer",99)));
 sv.push_back(Sales_item(Bulk_item("Algorithm",80,2,0.3)));
 sv.push_back(Sales_item(Bulk_item("The art of programming",60,3,0.1)));

 for(std::vector<Sales_item>::size_type sz=0;sz<sv.size();sz++)
 {
  std::cout<<"Name : "<<sv[sz]->get_isbn()<<" Price: "<<sv[sz]->net_price(1)<<std::endl;
 }
 
 return 0;
}

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值