zoukankan      html  css  js  c++  java
  • c/c++ 继承与多态 容器与继承3

    c/c++ 继承与多态 容器与继承2 巩固了容器里放智能指针的用法,但是有个问题,对于使用Basket类的用户来说,必须添加的是智能指针,如果能直接添加一个普通的类的对象的话,用起来就方便的多了,所以改进一下Basket类的add_item接口。

    新的接口:一个是拷贝给定的对象,另一个是移动对象。

    void add_item(const Quote& sale);//左值拷贝
    void add_item(Quote&& sale);//右值移动
    

    关键点:

    1,由于类Quote没有自定义的拷贝控制成员(拷贝构造函数,赋值语句等),所以,编译器才能自动生成移动构造函数,后面要用到编译器生成移动构造函数。

    2,由于key是智能指针,所以在方法add_item里必须要有new,问题来了,new谁呢,只能new父类Quote,但是new了Quote后,子类部分就被切除掉了。

    3,为了解决在2处的问题,在Quote和它的子类里添加辅助的虚函数,来得到正确的指针。得到了正确的普通指针就可以用普通指针做出智能指针了。

    Quote4.h

    #ifndef __QUOTE4_H__
    #define __QUOTE4_H__
    
    #include <iostream>
    
    class Quote{
     public:
      Quote() = default;
      Quote(const std::string& book, double pri)
        :bookNo(book), price(pri){}
      std::string isbn() const{return bookNo;}
    
      
      //调用此方法的对象是左值的时候
      virtual Quote* clone() const & {
        //调用合成的拷贝构造函数
        return new Quote(*this);
      }
    
      ///调用此方法的对象是右值的时候
      virtual Quote* clone() && {
        //调用合成的移动构造函数
        return new Quote(std::move(*this));
      }
    
    
    
      virtual double net_price(std::size_t n)const{
        return n * price;
      }
      virtual void debug()const{
        std::cout << bookNo << " " << price << std::endl;
      }
      virtual ~Quote() = default;
     private:
      std::string bookNo;
     protected:
      double price = 0.0;
    };
    
    class Disc_quote : public Quote{
     public:
      Disc_quote() = default;
      Disc_quote(const std::string& book, double price,
    	     std::size_t qyn, double disc):Quote(book, price),
        quantity(qyn), discount(disc){}
      
      double net_price(std::size_t) const override = 0;
     protected:
      std::size_t quantity = 0;//折扣适用的数量
      double discount = 0.0;   //折扣率
    };
    
    class Bulk_quote : public Disc_quote{
     public:
      
      Bulk_quote() = default;
      
      Bulk_quote(const std::string& book, double price,
      std::size_t qyn, double disc)
      :Disc_quote(book, price, qyn, disc){}
    
    
      //调用此方法的对象是左值的时候
      Bulk_quote* clone() const & {
        //调用合成的拷贝构造函数
        return new Bulk_quote(*this);
      }
    
      ///调用此方法的对象是右值的时候
      Bulk_quote* clone() && {
        //调用合成的移动构造函数
        return new Bulk_quote(std::move(*this));
      }
    
      
      double net_price(std::size_t) const override;
    };
    
    class Min_quote : public Disc_quote{
     public:
      
      Min_quote() = default;
      Min_quote(const std::string& book, double price,
      	   std::size_t qyn, double disc)
       :Disc_quote(book, price, qyn, disc){}
      
      double net_price(std::size_t) const override;
    };
    
    #endif
    
    

    Quote4.cpp

    #include "Quote4.h"
    
    double Bulk_quote::net_price(std::size_t cnt) const{
      if(cnt >= quantity){
        return cnt * (1 - discount) * price;
      }
      else{
        return cnt * price;
      }
    }
    
    
    double Min_quote::net_price(std::size_t cnt) const{
      if(cnt < quantity){
        return cnt * (1 - discount) * price;
      }
      else{
        return cnt * price;
      }
    }
    
    
    

    Basket2.h

    #ifndef __BASKET2_H__
    #define __BASKET2_H__
    #include "Quote4.h"
    #include <set>
    #include <memory>
    
    
    class Basket{
     public:
      /*
      void add_item(const std::shared_ptr<Quote>& sale){
        items.insert(sale);
      }
      */
    
      void add_item(const Quote& sale){
        items.insert(std::shared_ptr<Quote>(sale.clone()));
      }
      void add_item(Quote&& sale){
        items.insert(std::shared_ptr<Quote>(std::move(sale).clone()));
      }
      
      double total_receipt(std::ostream&) const;
     private:
      static bool compare(const std::shared_ptr<Quote>& lhs,
    		      const std::shared_ptr<Quote>& rhs){
        return lhs->isbn() < rhs->isbn();
      }
      std::multiset<std::shared_ptr<Quote>, decltype(compare)*>
        items{compare};
    };
    
    #endif
    
    

    Basket2.cpp

    #include "Basket.h"
    
    double print_total(std::ostream& os,
    		   const Quote& item, size_t n);
    double Basket::total_receipt(std::ostream& os) const{
      double sum = 0.0;
      for(auto iter = items.cbegin();
          iter != items.cend();
          iter = items.upper_bound(*iter)){
        sum += print_total(os, **iter, items.count(*iter));
      }
      os << "Total Sale: " << sum << std::endl;
      return sum;
    }
    
    

    main.cpp

    #include "Quote4.h"
    #include "Basket2.h"
    #include <vector>
    #include <iostream>
    
    double print_total(std::ostream& os,
    		   const Quote& item, size_t n){
      double ret = item.net_price(n);
      os << "ISBN: " << item.isbn()
         << " # sold: " << n << " total due: " << ret << std::endl;
      return ret;
    
    }
    
    int main(){
      Basket bsk;
      Quote q1("01", 100);
      Bulk_quote bq1("01", 100, 2, 0.1);
      bsk.add_item(Quote("01", 100));
    
      bsk.add_item(Bulk_quote("01", 100, 2, 0.1));
    
      bsk.total_receipt(std::cout);
    }
    
    

    c/c++ 学习互助QQ群:877684253

    本人微信:xiaoshitou5854

  • 相关阅读:
    DDOS攻击事件记录
    ansible批量安装zabbix客户端并实现自动发现功能
    利用api更新域名解析ip+端口转发【2】
    利用api更新域名解析ip+端口转发【1】
    网站春节开市休市设置
    获取内网路由器管理页面出口ip
    关于nginx加载配置文件的巨坑
    活动封禁刷票ip
    二十五个Python高级开发技巧,终极干货!建议收藏学习!
    一则故事带你秒懂Python GIL原理!
  • 原文地址:https://www.cnblogs.com/xiaoshiwang/p/10220481.html
Copyright © 2011-2022 走看看