zoukankan      html  css  js  c++  java
  • C++

    复制(copy) 和 虚复制(virtual copy) 的 区别

    本文地址: http://blog.csdn.net/caroline_wendy/article/details/16120397

    在继承过程中, 需要区分复制(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
    


  • 相关阅读:
    输入属性,输出属性
    angular响应式表单
    angular 响应式表单指令
    c++ Primer
    CString 操作函数
    字符串分割strtok_s
    LPSTR LPTSTR
    CString分割切分
    CStringArray
    十进制
  • 原文地址:https://www.cnblogs.com/riskyer/p/3424240.html
Copyright © 2011-2022 走看看