【人迹C++primer】55、容器和继承

【足迹C++primer】55、容器和继承

容器和继承

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

【人迹C++primer】55、容器和继承