容器和继承
class Quote
{
public:
Quote()=default; //默认构造函数
Quote(const string &book, double sales_price):bookNo(book), price(sales_price)
{cout<<"Quote gouzhao function"<<endl;}
//拷贝函数
Quote(const Quote&)=default;
Quote(Quote&&)=default;
//拷贝赋值运算符,和移动赋值运算符
Quote& operator=(const Quote&)=default;
Quote& operator=(Quote&&)=default;
//析构函数
virtual ~Quote()=default; //动态链接析构函数
string isbn() const {return bookNo;}
//返回指定数量的项目总销售价格
//派生类将重写应用不同的折扣算法
virtual double net_price(size_t n) const {return n*price;}
private:
string bookNo; //这本书的isbn号
protected:
double price=0.0; //不打折的价格
};
class Bulk_quote : public Quote
{
public:
Bulk_quote()=default;
Bulk_quote(const string & book, double p, size_t qty, double disc)
: Quote(book, p), min_qty(qty), discount(disc)
{cout<<"Bulk_quote construct function"<<endl;}
//重写虚函数
double net_price(size_t n) const override {cout<<"double net_price(size_t)"<<endl; return n*price*(1-discount);}
//再次说明,请声明函数后一定要记得定义它,不然我这是出了各种莫名其妙的错误!
// ~Bulk_quote2(){cout<<"~Bulk_quote2()"<<endl;}
///--------------------------------
pair<size_t, double> discount_policy() const {return {min_qty, discount};}
private:
size_t min_qty=0;
double discount=0.0;
};
void fun1()
{
vector<Quote> basket;
basket.push_back(Quote("0-201-82470-1", 50));
//ok:以下拷贝Quote部分进入basket,其余部分会被无视掉
basket.push_back(Bulk_quote("0-201-54848-8", 50, 10, 0.25));
//调用Quote定义的版本输出750,i.e.,15*$50;
cout<<basket.back().net_price(15)<<endl;
}
Because derived objects are “sliced down” when assigned to a base-type
object, containers and types related by inheritance do not mix well.
不要问我为什么,有的翻译有的不翻译,翻译软件你懂得。
Put (Smart) Pointers, Not Objects, in Containers
void fun2()
{
vector<shared_ptr<Quote>> basket;
basket.push_back(make_shared<Quote>("0-201-82470-1", 50));
basket.push_back(make_shared<Bulk_quote>("0-201-54848-8", 50, 10, 0.25));
//调用Quote定义的版本,输出562.5,i.e.,15*$50 少于discount
cout<<basket.back()->net_price(15)<<endl;
}
Writing a Basket Class
class Basket
{
public:
//使用合成的默认构造函数和复制控制成员
void add_item(const shared_ptr<Quote> &sale) {items.insert(sale); }
double total_receipt(ostream&) const;
private:
static bool compare(const shared_ptr<Quote> &lhs, const shared_ptr<Quote> &rhs)
{return lhs->isbn() < rhs->isbn(); }
///--------------------------------------------
multiset<shared_ptr<Quote>, decltype(compare)*> items {compare}; //这TM是什么玩意!!我是不太明白了
///--------------------------------------------
/*
This declaration can be hard to read, but reading from left to right, we see that we
are defining a multiset of shared_ptrs to Quote objects. The multiset will use
a function with the same type as our compare member to order the elements. The
multiset member is named items, and we’re initializing items to use our
compare function.
*/
};
Defining the Members of Basket
//lower_bound( const key_type &key ): 返回一个迭代器,指向键值>= key的第一个元素
//upper_bound:返回一个迭代器,指向键值>key的第一个元素。
double print_total(ostream &os, const Quote &item, size_t n)
{
// depending on the type of the object bound to the item parameter
// calls either Quote::net_price or Bulk_quote::net_price
double ret = item.net_price(n);
os << "ISBN: " << item.isbn() // calls Quote::isbn
<< " # sold: " << n << " total due: " << ret << endl;
return ret;
}
double Basket::total_receipt(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));
//这个count统计quote对象,主要是isbn号一样的quote,统计买这本书的个数
}
os<<"Total Sale:"<<sum<<endl;
return sum;
}
虚拟复制
虚函数返回一个自身的动态内存分配
这些成员用引用
函数后面加&返回一个左值&&表示返回右值
注意C++中new产生的是一个指针Java中是一个引用
class Quote2
{
public:
virtual Quote2* clone() const & {return new Quote2(*this);}
virtual Quote2* clone() && {return new Quote2(std::move(*this));}
Quote2()=default; //默认构造函数
Quote2(const string &book, double sales_price):bookNo(book), price(sales_price)
{cout<<"Quote2 gouzhao function"<<endl;}
//拷贝函数
Quote2(const Quote2&)=default;
Quote2(Quote2&&)=default;
//拷贝赋值运算符,和移动赋值运算符
Quote2& operator=(const Quote2&)=default;
Quote2& operator=(Quote2&&)=default;
//析构函数
virtual ~Quote2()=default; //动态链接析构函数
string isbn() const {return bookNo;}
//返回指定数量的项目总销售价格
//派生类将重写应用不同的折扣算法
virtual double net_price(size_t n) const {return n*price;}
private:
string bookNo; //这本书的isbn号
protected:
double price=0.0; //不打折的价格
};
class Bulk_quote2 : public Quote2
{
public:
Bulk_quote2* clone() const & {return new Bulk_quote2(*this);}
Bulk_quote2* clone() && {return new Bulk_quote2(std::move(*this));}
Bulk_quote2()=default;
Bulk_quote2(const string & book, double p, size_t qty, double disc)
: Quote2(book, p), min_qty(qty), discount(disc)
{cout<<"Bulk_quote2 construct function"<<endl;}
//重写虚函数
double net_price(size_t n) const override {cout<<"double net_price(size_t)"<<endl; return n*price*(1-discount);}
//再次说明,请声明函数后一定要记得定义它,不然我这是出了各种莫名其妙的错误!
// ~Bulk_quote2(){cout<<"~Bulk_quote2()"<<endl;}
///--------------------------------
pair<size_t, double> discount_policy() const {return {min_qty, discount};}
private:
size_t min_qty=0;
double discount=0.0;
};
由于add_item将会有两个版本,那么会定义两个clone
class Basket2
{
public:
void add_item(const Quote2 & sale) //拷贝添加
{items.insert(shared_ptr<Quote2>(sale.clone()));}
void add_item(Quote2 && sale) //引用添加
{items.insert(shared_ptr<Quote2>(std::move(sale).clone()));}
//这里我不知道和std::move(sale.clone)()))有没有差别啊
//我认为这里移动的是sale移动之后进行clone操作,就是移动之后对移动后的数据进行操作这和
//吧数据操作之后移动,有一点差别,如果数据空间没变那就没关系,否则前面和后面会不一样
//使用合成的默认构造函数和复制控制成员
void add_item(const shared_ptr<Quote2> &sale) {items.insert(sale); }
double total_receipt(ostream&) const;
private:
static bool compare(const shared_ptr<Quote2> &lhs, const shared_ptr<Quote2> &rhs)
{return lhs->isbn() < rhs->isbn(); }
///--------------------------------------------
multiset<shared_ptr<Quote2>, decltype(compare)*> items {compare}; //这TM是什么玩意!!我是不太明白了
///--------------------------------------------
};
double print_total2(ostream &os, const Quote2 &item, size_t n)
{
// depending on the type of the object bound to the item parameter
// calls either Quote2::net_price or Bulk_quote::net_price
double ret = item.net_price(n);
os << "ISBN: " << item.isbn() // calls Quote2::isbn
<< " # sold: " << n << " total due: " << ret << endl;
return ret;
}
double Basket2::total_receipt(ostream &os) const
{
double sum=0.0; //保存总数,最后返回
for(auto iter=items.cbegin() ; iter != items.cend() ; iter=items.upper_bound(*iter))
{
sum+=print_total2(os, **iter, items.count(*iter));
//这个count统计quote对象,主要是isbn号一样的quote,统计买这本书的个数
}
os<<"Total Sale:"<<sum<<endl;
return sum;
}
void fun3()
{
Basket2 bsk2;
/*bsk2.add_item(std::make_shared<Quote>("CppPrimer", 45));
bsk2.add_item(std::make_shared<Bulk_quote>("EffectiveCpp", 50, 2, 0.15));
bsk2.add_item(std::make_shared<Bulk_quote>("EffectiveCpp", 50, 2, 0.15));
bsk2.add_item(std::make_shared<Bulk_quote>("EffectiveCpp", 50, 2, 0.15));*/
bsk2.add_item(Quote2("Quote2->cutter_point", 45));
bsk2.add_item(Bulk_quote2("Bulk_quote2->EffectiveCpp", 50, 2, 0.15));
bsk2.add_item(Bulk_quote2("Bulk_quote2->EffectiveCpp", 50, 2, 0.15));
bsk2.add_item(Bulk_quote2("Bulk_quote2->EffectiveCpp", 50, 2, 0.15));
bsk2.total_receipt(cout);
}
the all code
/**
* 功能:容器和继承
* 时间:2014年7月22日17:10:39
* 作者:cutter_point
*/
#include<iostream>
#include<algorithm>
#include<vector>
#include<memory>
#include<set>
using namespace std;
class Quote
{
public:
Quote()=default; //默认构造函数
Quote(const string &book, double sales_price):bookNo(book), price(sales_price)
{cout<<"Quote gouzhao function"<<endl;}
//拷贝函数
Quote(const Quote&)=default;
Quote(Quote&&)=default;
//拷贝赋值运算符,和移动赋值运算符
Quote& operator=(const Quote&)=default;
Quote& operator=(Quote&&)=default;
//析构函数
virtual ~Quote()=default; //动态链接析构函数
string isbn() const {return bookNo;}
//返回指定数量的项目总销售价格
//派生类将重写应用不同的折扣算法
virtual double net_price(size_t n) const {return n*price;}
private:
string bookNo; //这本书的isbn号
protected:
double price=0.0; //不打折的价格
};
class Bulk_quote : public Quote
{
public:
Bulk_quote()=default;
Bulk_quote(const string & book, double p, size_t qty, double disc)
: Quote(book, p), min_qty(qty), discount(disc)
{cout<<"Bulk_quote construct function"<<endl;}
//重写虚函数
double net_price(size_t n) const override {cout<<"double net_price(size_t)"<<endl; return n*price*(1-discount);}
//再次说明,请声明函数后一定要记得定义它,不然我这是出了各种莫名其妙的错误!
// ~Bulk_quote2(){cout<<"~Bulk_quote2()"<<endl;}
///--------------------------------
pair<size_t, double> discount_policy() const {return {min_qty, discount};}
private:
size_t min_qty=0;
double discount=0.0;
};
void fun1()
{
vector<Quote> basket;
basket.push_back(Quote("0-201-82470-1", 50));
//ok:以下拷贝Quote部分进入basket,其余部分会被无视掉
basket.push_back(Bulk_quote("0-201-54848-8", 50, 10, 0.25));
//调用Quote定义的版本输出750,i.e.,15*$50;
cout<<basket.back().net_price(15)<<endl;
}
/*
Because derived objects are “sliced down” when assigned to a base-type
object, containers and types related by inheritance do not mix well.
不要问我为什么,有的翻译有的不翻译,翻译软件你懂得。
*/
/**
Put (Smart) Pointers, Not Objects, in Containers
*/
void fun2()
{
vector<shared_ptr<Quote>> basket;
basket.push_back(make_shared<Quote>("0-201-82470-1", 50));
basket.push_back(make_shared<Bulk_quote>("0-201-54848-8", 50, 10, 0.25));
//调用Quote定义的版本,输出562.5,i.e.,15*$50 少于discount
cout<<basket.back()->net_price(15)<<endl;
}
/**************************************
15.8.1. Writing a Basket Class
**************************************/
class Basket
{
public:
//使用合成的默认构造函数和复制控制成员
void add_item(const shared_ptr<Quote> &sale) {items.insert(sale); }
double total_receipt(ostream&) const;
private:
static bool compare(const shared_ptr<Quote> &lhs, const shared_ptr<Quote> &rhs)
{return lhs->isbn() < rhs->isbn(); }
///--------------------------------------------
multiset<shared_ptr<Quote>, decltype(compare)*> items {compare}; //这TM是什么玩意!!我是不太明白了
///--------------------------------------------
/*
This declaration can be hard to read, but reading from left to right, we see that we
are defining a multiset of shared_ptrs to Quote objects. The multiset will use
a function with the same type as our compare member to order the elements. The
multiset member is named items, and we’re initializing items to use our
compare function.
*/
};
/**
Defining the Members of Basket
*/
//lower_bound( const key_type &key ): 返回一个迭代器,指向键值>= key的第一个元素
//upper_bound:返回一个迭代器,指向键值>key的第一个元素。
double print_total(ostream &os, const Quote &item, size_t n)
{
// depending on the type of the object bound to the item parameter
// calls either Quote::net_price or Bulk_quote::net_price
double ret = item.net_price(n);
os << "ISBN: " << item.isbn() // calls Quote::isbn
<< " # sold: " << n << " total due: " << ret << endl;
return ret;
}
double Basket::total_receipt(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));
//这个count统计quote对象,主要是isbn号一样的quote,统计买这本书的个数
}
os<<"Total Sale:"<<sum<<endl;
return sum;
}
/**
虚拟复制
*/
//虚函数返回一个自身的动态内存分配
//这些成员用引用
//函数后面加&返回一个左值&&表示返回右值
//注意C++中new产生的是一个指针Java中是一个引用
class Quote2
{
public:
virtual Quote2* clone() const & {return new Quote2(*this);}
virtual Quote2* clone() && {return new Quote2(std::move(*this));}
Quote2()=default; //默认构造函数
Quote2(const string &book, double sales_price):bookNo(book), price(sales_price)
{cout<<"Quote2 gouzhao function"<<endl;}
//拷贝函数
Quote2(const Quote2&)=default;
Quote2(Quote2&&)=default;
//拷贝赋值运算符,和移动赋值运算符
Quote2& operator=(const Quote2&)=default;
Quote2& operator=(Quote2&&)=default;
//析构函数
virtual ~Quote2()=default; //动态链接析构函数
string isbn() const {return bookNo;}
//返回指定数量的项目总销售价格
//派生类将重写应用不同的折扣算法
virtual double net_price(size_t n) const {return n*price;}
private:
string bookNo; //这本书的isbn号
protected:
double price=0.0; //不打折的价格
};
class Bulk_quote2 : public Quote2
{
public:
Bulk_quote2* clone() const & {return new Bulk_quote2(*this);}
Bulk_quote2* clone() && {return new Bulk_quote2(std::move(*this));}
Bulk_quote2()=default;
Bulk_quote2(const string & book, double p, size_t qty, double disc)
: Quote2(book, p), min_qty(qty), discount(disc)
{cout<<"Bulk_quote2 construct function"<<endl;}
//重写虚函数
double net_price(size_t n) const override {cout<<"double net_price(size_t)"<<endl; return n*price*(1-discount);}
//再次说明,请声明函数后一定要记得定义它,不然我这是出了各种莫名其妙的错误!
// ~Bulk_quote2(){cout<<"~Bulk_quote2()"<<endl;}
///--------------------------------
pair<size_t, double> discount_policy() const {return {min_qty, discount};}
private:
size_t min_qty=0;
double discount=0.0;
};
/*
由于add_item将会有两个版本,那么会定义两个clone
*/
class Basket2
{
public:
void add_item(const Quote2 & sale) //拷贝添加
{items.insert(shared_ptr<Quote2>(sale.clone()));}
void add_item(Quote2 && sale) //引用添加
{items.insert(shared_ptr<Quote2>(std::move(sale).clone()));}
//这里我不知道和std::move(sale.clone)()))有没有差别啊
//我认为这里移动的是sale移动之后进行clone操作,就是移动之后对移动后的数据进行操作这和
//吧数据操作之后移动,有一点差别,如果数据空间没变那就没关系,否则前面和后面会不一样
//使用合成的默认构造函数和复制控制成员
void add_item(const shared_ptr<Quote2> &sale) {items.insert(sale); }
double total_receipt(ostream&) const;
private:
static bool compare(const shared_ptr<Quote2> &lhs, const shared_ptr<Quote2> &rhs)
{return lhs->isbn() < rhs->isbn(); }
///--------------------------------------------
multiset<shared_ptr<Quote2>, decltype(compare)*> items {compare}; //这TM是什么玩意!!我是不太明白了
///--------------------------------------------
};
double print_total2(ostream &os, const Quote2 &item, size_t n)
{
// depending on the type of the object bound to the item parameter
// calls either Quote2::net_price or Bulk_quote::net_price
double ret = item.net_price(n);
os << "ISBN: " << item.isbn() // calls Quote2::isbn
<< " # sold: " << n << " total due: " << ret << endl;
return ret;
}
double Basket2::total_receipt(ostream &os) const
{
double sum=0.0; //保存总数,最后返回
for(auto iter=items.cbegin() ; iter != items.cend() ; iter=items.upper_bound(*iter))
{
sum+=print_total2(os, **iter, items.count(*iter));
//这个count统计quote对象,主要是isbn号一样的quote,统计买这本书的个数
}
os<<"Total Sale:"<<sum<<endl;
return sum;
}
void fun3()
{
Basket2 bsk2;
/*bsk2.add_item(std::make_shared<Quote>("CppPrimer", 45));
bsk2.add_item(std::make_shared<Bulk_quote>("EffectiveCpp", 50, 2, 0.15));
bsk2.add_item(std::make_shared<Bulk_quote>("EffectiveCpp", 50, 2, 0.15));
bsk2.add_item(std::make_shared<Bulk_quote>("EffectiveCpp", 50, 2, 0.15));*/
bsk2.add_item(Quote2("Quote2->cutter_point", 45));
bsk2.add_item(Bulk_quote2("Bulk_quote2->EffectiveCpp", 50, 2, 0.15));
bsk2.add_item(Bulk_quote2("Bulk_quote2->EffectiveCpp", 50, 2, 0.15));
bsk2.add_item(Bulk_quote2("Bulk_quote2->EffectiveCpp", 50, 2, 0.15));
bsk2.total_receipt(cout);
}
int main()
{
cout<<">>------------------------------fun1-----------------------------------<<"<<endl;
fun1();
cout<<">>------------------------------fun2-----------------------------------<<"<<endl;
fun2();
cout<<">>------------------------------fun3-----------------------------------<<"<<endl;
fun3();
system("pause");
return 0;
}
show the result