• 虚拷贝


    当传入对象时,函数有时会需要拷贝该对象并存入容器中,例如:

    类定义:

     1 class Quote {  
     2 public:  
     3     Quote() = default;  
     4     Quote (const std::string& book, double sales_price) :  
     5         bookNo (book), price (sales_price) {}  
     6     void add_item (const Quote& sale);  
     7     std::string isbn() const { return bookNo; }  
     8     virtual double net_price (std::size_t n) const { return n* price; } //虚函数  
     9     virtual Quote* clone() const & {return new Quote(*this);}  
    10     virtual Quote* clone() && {return new Quote(std::move(*this));}  
    11     virtual ~Quote() = default; //动态绑定析构器  
    12 private:  
    13     std::string bookNo;  
    14 protected: //受保护类型  
    15     double price = 0.0;  
    16 };  
    17   
    18 class Disc_quote : public Quote { //抽象基类  
    19 public:  
    20     Disc_quote() = default;  
    21     Disc_quote (const std::string& book, double price, std::size_t qty, double disc) :  
    22         Quote(book, price), quantity (qty), discount (disc) {}  
    23     double net_price (std::size_t) const = 0; //纯虚函数  
    24 protected:  
    25         std::size_t quantity = 0;  
    26         double discount = 0.0;  
    27 };  
    28   
    29 class Bulk_quote final : public Disc_quote { //final限定词, 无法被继承  
    30 public:  
    31     Bulk_quote() = default;  
    32     Bulk_quote(const std::string& book, double p, std::size_t qty, double disc) :  
    33         Disc_quote(book, p, qty, disc) {} //使用基类的构造器  
    34     double net_price(std::size_t cnt) const override;  
    35     virtual Bulk_quote* clone() const & {return new Bulk_quote(*this);}  
    36     virtual Bulk_quote* clone() && {return new Bulk_quote(std::move(*this));}  
    37 };  

    函数定义:

    1 void add_item(const Quote& sale);   //拷贝给定的对象
    2 void add_item(Quote&& sale);         //移动给定的对象

    然而此时,add_item并不知道要分配的类型。当add_item进行内存分配时,它将拷贝sale参数,如

    new Quote(sale)

    然而这条表达式却可能是不正确的:new为我们请求的类型分配内存,因此它将分配一个Quote类型的对象并拷贝sale的Quote部分,然而sale实际指向的可能是Bulk_quote对象,此时add_item所拷贝的对象将失去一部分信息。

    为了解决该问题,我们给Quote类添加了一个虚函数,该函数将申请一份当前对象的拷贝。

     1 class Quote {
     2 public:
     3     virtual Quote* clone() const & { return new Quote(*this); }
     4     virtual Quote* clone() && {return new Quote(std::move(*this)); }
     5 };
     6 class Bulk_quote final : public Disc_quote { 
     7 public:
     8     virtual Bulk_quote* clone() const & { return new Bulk_quote(*this); }
     9     virtual Bulk_quote* clone() && {return new Bulk_quote(std::move(*this)); }
    10 };

    这样每个clone函数分配当前类型的一个新对象,其中,const左值引用成员将它自己拷贝给新分配的对象;右值引用成员则将自己移动到新数据中。

    这样,我们可以使用clone写出新版本的add_item:

     1 void add_item (const Quote& sale)  
     2     {  
     3         //items.insert(std::shared_ptr<Quote>(new Quote(sale))); //不会动态绑定  
     4         items.insert(std::shared_ptr<Quote>(sale.clone()));  
     5     }  
     6     void add_item (Quote&& sale)  
     7     {  
     8         //items.insert(std::shared_ptr<Quote>(new Quote(std::move(sale)))); //不会动态绑定  
     9         items.insert(std::shared_ptr<Quote>(std::move(sale).clone()));  
    10     }  
  • 相关阅读:
    spring data jpa删除的使用方式
    javax.persistence.TransactionRequiredException: No transactional EntityManager available
    java.lang.ArithmeticException: Non-terminating decimal expansion; no exact representable decimal result异常的解决方法
    JS比较两个数组是否相等 是否拥有相同元素
    HttpSession的线程安全问题及注意事项
    easyui datagrid editor onBeforeEdit事件下使用getEditor和getEditors失效
    JQuery easyUi datagrid 中 editor 动态设置最大值最小值
    kaptcha验证码组件使用简介
    ohasd failed to start: Inappropriate ioctl for device
    web报表工具FineReport常见的数据集报错错误代码和解释
  • 原文地址:https://www.cnblogs.com/zl1991/p/8484813.html
Copyright © 2020-2023  润新知