C++ - 复制(copy) 和 虚复制(virtual copy) 的 区别
2013-11-14 18:03
239 查看
复制(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
\
相关文章推荐
- C++ - 复制(copy) 和 虚复制(virtual copy) 的 区别
- C++ - 复制(copy) 和 虚复制(virtual copy) 的 区别
- C++直接初始化与复制初始化的区别深入解析
- C++的一大误区——深入解释直接初始化与复制初始化的区别
- C++的一大误区——深入解释直接初始化与复制初始化的区别
- c++ 构造器的copy(拷贝), assignment(复制)
- C++深复制和浅复制的区别
- C++的一大误区——深入解释直接初始化与复制初始化的区别
- Arrays.copyof(···)与System.arraycopy(···)数组元素复制区别
- C++的一大误区——深入解释直接初始化与复制初始化的区别
- C++ Copy Constructor (拷贝构造函数,复制构造函数)
- C++的一大误区——深入解释直接初始化与复制初始化的区别
- bean之间的复制!BeanUtils.copyProperties、set、BeanCopier还有spring中的BeanUtils.copyProperties之间的区别
- C++的一大误区——深入解释直接初始化与复制初始化的区别
- C++的对象复制构造函数与赋值操作符重载的区别小结
- C++中构造函数,复制构造函数和赋值函数的区别和实现
- 对象复制copy与mutableCopy方法的区别
- C++的一大误区——深入解释直接初始化与复制初始化的区别
- C++的一大误区——深入解释直接初始化与复制初始化的区别
- C++的一大误区——深入解释直接初始化与复制初始化的区别