C++中複製(copy) 和 虛複製(virtual copy) 的 區別

來源:互聯網
上載者:User

在繼承過程中, 需要區分複製(copy)和虛複製(virtual copy);

在衍生類別轉換為基類時, 複製(copy)有可能切掉(sliced down)派生對象的派生部分, 只保留基類部分, 使衍生類別的虛函數無法使用;

為了避免此情況, 如果傳入是對象, 則可以定義虛函數clone, 使衍生類別繼承此虛函數, 再傳入容器, 可以重載方法;

另外, 如果傳入是實參, 使用shared_ptr<Base>配合make_shared<Derived>添加容器, 也可以進行動態綁定;

再傳入容器中, 容器會自動調用衍生類別的重載方法, 實現動態綁定;

注意: 引用限定符(reference qualifier) GCC 4.8.1 才能支援;

代碼:

/*  * CppPrimer.cpp  *  *  Created on: 2013.11.12  *      Author: Caroline  */      /*eclipse cdt*/      #include <iostream>  #include <string>  #include <vector>  #include <set>        #include <utility>  #include <memory>  #include <cstddef>        using namespace std;        class Quote;        class Quote {  public:      Quote() = default;      Quote (const std::string& book, double sales_price) :          bookNo (book), price (sales_price) {}      void add_item (const Quote& sale);      std::string isbn() const { return bookNo; }      virtual double net_price (std::size_t n) const { return n* price; } //虛函數      virtual Quote* clone() const & {return new Quote(*this);}      virtual Quote* clone() && {return new Quote(std::move(*this));}      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 qty, double disc) :          Quote(book, price), quantity (qty), discount (disc) {}      double net_price (std::size_t) const = 0; //純虛函數  protected:          std::size_t quantity = 0;          double discount = 0.0;  };        class Bulk_quote final : public Disc_quote { //final限定詞, 無法被繼承  public:      Bulk_quote() = default;      Bulk_quote(const std::string& book, double p, std::size_t qty, double disc) :          Disc_quote(book, p, qty, disc) {} //使用基類的構造器      double net_price(std::size_t cnt) const override;      virtual Bulk_quote* clone() const & {return new Bulk_quote(*this);}      virtual Bulk_quote* clone() && {return new Bulk_quote(std::move(*this));}  };        double Bulk_quote::net_price(std::size_t cnt) const{      if (cnt >= quantity)          return cnt * (1-discount) * price;      else        return cnt * price;  }        double print_total(std::ostream &os, const Quote& item, std::size_t n)  {      double ret = item.net_price(n);      os << "ISBN: " << item.isbn() << " # sold: " << n << " total due: " << ret << std::endl;      return ret;  }        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>(new Quote(sale))); //不會動態綁定          items.insert(std::shared_ptr<Quote>(sale.clone()));      }      void add_item (Quote&& sale)      {          //items.insert(std::shared_ptr<Quote>(new Quote(std::move(sale)))); //不會動態綁定          items.insert(std::shared_ptr<Quote>(std::move(sale).clone()));      }      double total_reciept (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};  };        double Basket::total_reciept(std::ostream &os) const{      double sum = 0.0;      for(auto iter = items.cbegin(); iter != items.cend();              iter = items.upper_bound(*iter)) { //跳過同名書, 直接計算count          sum += print_total(os, **iter, items.count(*iter)); //*it是shared_ptr; **it是object      }      os << "Total Sale: " << sum << std::endl;      return sum;  }        int main (void) {            Basket bsk;      /*bsk.add_item(std::make_shared<Quote>("CppPrimer", 45));      bsk.add_item(std::make_shared<Bulk_quote>("EffectiveCpp", 50, 2, 0.15));      bsk.add_item(std::make_shared<Bulk_quote>("EffectiveCpp", 50, 2, 0.15));      bsk.add_item(std::make_shared<Bulk_quote>("EffectiveCpp", 50, 2, 0.15));*/            bsk.add_item(Quote("CppPrimer", 45));      bsk.add_item(Bulk_quote("EffectiveCpp", 50, 2, 0.15));      bsk.add_item(Bulk_quote("EffectiveCpp", 50, 2, 0.15));      bsk.add_item(Bulk_quote("EffectiveCpp", 50, 2, 0.15));            bsk.total_reciept(std::cout);            return 0;        }

輸出:

ISBN: CppPrimer # sold: 1 total due: 45  ISBN: EffectiveCpp # sold: 3 total due: 127.5  Total Sale: 172.5

作者:csdn部落格 Spike_King

更多精彩內容:http://www.bianceng.cnhttp://www.bianceng.cn/Programming/cplus/

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.