欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

c/c++ 继承与多态 容器与继承3

程序员文章站 2022-07-10 12:06:46
"c/c++ 继承与多态 容器与继承2" 巩固了容器里放智能指针的用法,但是有个问题,对于使用Basket类的用户来说,必须添加的是智能指针,如果能直接添加一个普通的类的对象的话,用起来就方便的多了,所以改进一下Basket类的add_item接口。 新的接口:一个是拷贝给定的对象,另一个是移动对象 ......

巩固了容器里放智能指针的用法,但是有个问题,对于使用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

c/c++ 继承与多态 容器与继承3

本人微信:xiaoshitou5854