【人迹C++primer】55、容器和继承
【足迹C++primer】55、容器和继承
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
Writing a Basket Class
Defining the Members of Basket
虚拟复制
由于add_item将会有两个版本,那么会定义两个clone
容器和继承
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; }