c++ primer中文版第五版作业第十五章

仓库地址

文章目录

      • 15.1
      • 15.2
      • 15.3
      • 15.4
      • 15.5
      • 15.6
      • 15.7
      • 15.8
      • 15.9
      • 15.10
      • 15.11
      • 15.12
      • 15.13
      • 15.14
      • 15.15
      • 15.16
      • 15.17
      • 15.18
      • 15.19
      • 15.20
      • 15.21
      • 15.22
      • 15.23
      • 15.24
      • 15.25
      • 15.26
      • 15.26
      • 15.28
      • 15.29
      • 15.30
      • 15.31
      • 15.32
      • 15.33
      • 15.34
      • 15.35
      • 15.36
      • 15.37
      • 15.38
      • 15.39
      • 15.40
      • 15.41
      • 15.42

15.1

 基类希望其派生类进行覆盖的函数,称为虚函数。任何构造函数之外的非静态函数都可以是虚函数。

15.2

 主要区别在于派生类的成员函数及其友元是否有其访问权限,protected说明符修饰的基类成员可以被派生类成员函数及其友元访问,同时禁止派生类用户访问。而private说明符修饰的基类成员不能被派生类成员函数及其友元访问,也禁止派生类用户访问。

15.3

Quote.h

#ifndef _QUOTE_H
#define _QUOTE_H
#include <iostream>
#include <string>
class Quote
{public:Quote()=default;Quote(const std::string &book,double sales_price):price(sales_price),bookNo(book) {}std::string isbn() const {return bookNo;}virtual double net_price(std::size_t n) const {return n*price;}virtual std::string debug() const {return "bookNo="+bookNo+"\n"+"price="+std::to_string(price);}virtual ~Quote()=default;protected:double price=0.0;private:std::string bookNo;
};
double print_total(std::ostream &os,const Quote &item,std::size_t n);
class Bulk_quote:public Quote
{public:Bulk_quote()=default;Bulk_quote(const std::string &book,double sales_price,std::size_t qty,double disc):Quote(book,sales_price),min_qty(qty),discount(disc) {}virtual double net_price(std::size_t n) const override{if(n>=min_qty)return n*(1-discount)*price;elsereturn n*price;}virtual std::string debug() const{return Quote::debug()+"\n"+"min_qty="+std::to_string(min_qty)+"\n"+"discount="+std::to_string(discount);}private:std::size_t min_qty=0;double discount=0.0;
};class Limit_quote:public Quote
{public:Limit_quote()=default;Limit_quote(const std::string &book,double sales_price,std::size_t qty,double disc):Quote(book,sales_price),max_qty(qty),discount(disc) {}virtual double net_price(std::size_t n) const override{if(n<=max_qty)return n*(1-discount)*price;elsereturn max_qty*(1-discount)*price+(n-max_qty)*price;}virtual std::string debug() const{return Quote::debug()+"\n"+"max_qty="+std::to_string(max_qty)+"\n"+"discount="+std::to_string(discount);}private:std::size_t max_qty=0;double discount=0.0;
};
#endif

Quote.cpp

#include "Quote.h"
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;
}

15.4

  1. 错误,一个类不能派生它本身。
  2. 正确。
  3. 错误,派生类的声明中不可以包含它的派生列表。

15.5

见15.3

15.6

#include <iostream>
#include "Quote.h"
using namespace std;
int main(void)
{Quote item1("1-102-333",20);Bulk_quote item2("1-202-222",30,2,0.2);print_total(cout,item1,3);print_total(cout,item2,3);return 0;
}

15.7

class Limit_quote:public Quote
{public:Limit_quote()=default;Limit_quote(const std::string &book,double sales_price,std::size_t qty,double disc):Quote(book,sales_price),max_qty(qty),discount(disc) {}virtual double net_price(std::size_t n) const override{if(n<=max_qty)return n*(1-discount)*price;elsereturn max_qty*(1-discount)*price+(n-max_qty)*price;}private:std::size_t max_qty=0;double discount=0.0;
};

15.8

静态类型是变量声明时的类型或表达式生成的类型,动态类型则是变量或表达式表示的内存中的对象的类型,动态类型直到运行时才可知。

15.9

 当基类的指针或引用指向派生类对象时,就会产生静态类型与动态类型不同的情况。

class base{......};
class derived:public base{......};
derived objd;
base *bp=&objd;//这三种情况静态类型与动态类型不同
base &bref=objd;//这三种情况静态类型与动态类型不同
base *bp=derived *dp=&objd;//这三种情况静态类型与动态类型不同

15.10

ifstream类型派生自istream类型,因此我们可以像使用istream对象一样使用ifstream对象。在read函数中,它接受一个istream类型的引用,所以作为它派生类,ifstream也可以绑定到istream的引用上。

15.11

见15.3

15.12

 有必要,override关键字指明该函数用于覆盖掉从基类继承而来的虚函数,这种用法可以避免我们在派生类中不经意间定义了一个与继承而来的虚函数同名但形参列表不同,而导致重新声明了一个与原虚函数相互独立的的函数的情况。而final关键字指明该函数不允许后续的派生类进行覆盖。这两个关键字功能并不重复,所以可以同时声明。

15.13

 两个print函数的目的都是打印各自的数据成员,其中派生类的print函数,函数体中会对自身版本的print函数进行调用,从而导致无限递归。派生类中的print函数应该改为void print(ostream &os) {base::print(os);os<<" "<<i;}

15.14

  1. 基类版本
  2. 派生类版本
  3. 基类版本
  4. 基类版本
  5. 基类版本
  6. 派生类版本

15.15

Quote.h

#ifndef _QUOTE_H
#define _QUOTE_H
#include <iostream>
#include <string>
class Quote
{public:Quote()=default;Quote(const std::string &book,double sales_price):price(sales_price),bookNo(book) {}std::string isbn() const {return bookNo;}virtual double net_price(std::size_t n) const {return n*price;}virtual std::string debug() const {return "bookNo="+bookNo+"\n"+"price="+std::to_string(price);}virtual ~Quote()=default;protected:double price=0.0;private:std::string bookNo;
};
class Disc_quote:public Quote
{public:Disc_quote()=default;Disc_quote(const std::string &book,double sales_price,std::size_t qty,double disc):Quote(book,sales_price),quantity(qty),discount(disc) {}virtual double net_price(std::size_t n) const=0;virtual std::string debug() const override{return Quote::debug()+"\n"+"quantity="+std::to_string(quantity)+"\n"+"discount="+std::to_string(discount);}protected:std::size_t quantity=0;double discount=0.0;
};
double print_total(std::ostream &os,const Quote &item,std::size_t n);
class Bulk_quote:public Disc_quote
{public:Bulk_quote()=default;Bulk_quote(const std::string &book,double sales_price,std::size_t qty,double disc):Disc_quote(book,sales_price,qty,disc) {}virtual double net_price(std::size_t n) const override{if(n>=quantity)return n*(1-discount)*price;elsereturn n*price;}
};
class Limit_quote:public Disc_quote
{public:Limit_quote()=default;Limit_quote(const std::string &book,double sales_price,std::size_t qty,double disc):Disc_quote(book,sales_price,qty,disc) {}virtual double net_price(std::size_t n) const override{if(n<=quantity)return n*(1-discount)*price;elsereturn quantity*(1-discount)*price+(n-quantity)*price;}
};
#endif

Quote.cpp

#include "Quote.h"
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;
}

15.16

见15.15

15.17

test.cpp:5:20: error: cannot declare variable ‘item’ to be of abstract type ‘Disc_quote’

15.18

Base *p=&d1合法
p=&d2不合法,在用户代码层面,私有继承的派生类的基类部分是不可访问的
p=&d3不合法,在用户代码层面,保护继承的派生类的基类部分是不可访问的
p=&dd1合法
p=&dd2不合法,基类部分不可访问
p=&dd3不合法,基类部分不可访问

15.19

struct Derived_from_Private:public Priv_Derv这个类中的memfcn不合法。
 不论以何种方式继承,派生类的成员函数和友元都能使用派生类向基类的转换。派生类向其直接基类的类型转换对于派生类的成员和友元来说永远是可访问的。
 如果派生类以公有或者受保护的方式继承,则派生类的派生类的成员和友元可以使用派生类向其基类的类型转换。如果以私有方式继承,则不能使用。

15.20

15.21

图形
平面图形
立体图形
方格
圆锥

其中图形、平面图形及立体图形类都是抽象基类.
以后再写

15.22

见15.21

15.23

class D1:public Base
{public:int fcn();virtual void f2();
};

bp2->fcn();虚调用,将在运行时调用D1::fcn.
p2->fcn(42);错误,D1中没有一个接受int的fcn.

15.24

 继承体系中的基类需要虚析构函数。虚析构函数可以在delete基类指针指向的派生类对象时,调用正确版本的析构函数。

15.25

 编译器只有在发现类不包含任何构造函数的情况下才会替我们生成一个合成的默认构造函数,因为Disc_quote定义了其它的构造函数,所以不会自动生成一个合成的默认构造函数,如此一来它的派生类Bulk_quote也不能生成合成的默认构造函数。

15.26

Quote.h

#ifndef _QUOTE_H
#define _QUOTE_H
#include <iostream>
#include <string>
class Quote
{public:Quote()=default;Quote(const Quote &rhs):price(rhs.price),bookNo(rhs.bookNo) {std::cout<<"Quote copy constructor"<<std::endl;}Quote(Quote &&rhs) noexcept :price(rhs.price),bookNo(std::move(rhs.bookNo)) {std::cout<<"Quote move constructor"<<std::endl;}Quote & operator=(const Quote &rhs){std::cout<<"Quote copy assignment operator"<<std::endl;price=rhs.price;bookNo=rhs.bookNo;return *this;}Quote & operator=(Quote &&rhs) noexcept{std::cout<<"Quote move assignment operator"<<std::endl;if(this!=&rhs){price=rhs.price;bookNo=std::move(rhs.bookNo);}return *this;}Quote(const std::string &book,double sales_price):price(sales_price),bookNo(book) {}std::string isbn() const {return bookNo;}virtual double net_price(std::size_t n) const {return n*price;}virtual std::string debug() const {return "bookNo="+bookNo+"\n"+"price="+std::to_string(price);}virtual ~Quote()=default;protected:double price=0.0;private:std::string bookNo;
};
double print_total(std::ostream &os,const Quote &item,std::size_t n);
class Bulk_quote:public Quote
{public:Bulk_quote()=default;Bulk_quote(const std::string &book,double sales_price,std::size_t qty,double disc):Quote(book,sales_price),min_qty(qty),discount(disc) {}Bulk_quote(const Bulk_quote &rhs):Quote(rhs),min_qty(rhs.min_qty),discount(rhs.discount) {std::cout<<"Bulk_quote copy constructor"<<std::endl;}Bulk_quote(Bulk_quote &&rhs) noexcept : Quote(std::move(rhs)),min_qty(rhs.min_qty),discount(rhs.discount) {std::cout<<"Bulk_quote move constructor"<<std::endl;}Bulk_quote & operator=(const Bulk_quote &rhs){std::cout<<"Bulk_quote copy assignment operator"<<std::endl;Quote::operator=(rhs);min_qty=rhs.min_qty;discount=rhs.discount;return *this;}Bulk_quote & operator=(Bulk_quote &&rhs) noexcept{std::cout<<"Bulk_quote move assignment operator"<<std::endl;if(this!=&rhs){Quote::operator=(std::move(rhs));min_qty=rhs.min_qty;discount=rhs.discount;}return *this;}virtual double net_price(std::size_t n) const override{if(n>=min_qty)return n*(1-discount)*price;elsereturn n*price;}virtual std::string debug() const{return Quote::debug()+"\n"+"min_qty="+std::to_string(min_qty)+"\n"+"discount="+std::to_string(discount);}private:std::size_t min_qty=0;double discount=0.0;
};
#endif

Quote.cpp

#include "Quote.h"
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;
}

test.cpp

#include <iostream>
#include "Quote.h"
int main(void)
{Bulk_quote bulk("10-11-222",30,5,0.2);Quote qu=bulk;qu=bulk;Bulk_quote qu1=bulk;qu1=bulk;qu1=std::move(bulk);return 0;
}

15.26

Quote.h

#ifndef _QUOTE_H
#define _QUOTE_H
#include <iostream>
#include <string>
class Quote
{public:Quote()=default;Quote(const std::string &book,double sales_price):price(sales_price),bookNo(book) {}std::string isbn() const {return bookNo;}virtual double net_price(std::size_t n) const {return n*price;}virtual std::string debug() const {return "bookNo="+bookNo+"\n"+"price="+std::to_string(price);}virtual ~Quote()=default;protected:double price=0.0;private:std::string bookNo;
};
class Disc_quote:public Quote
{public:Disc_quote()=default;Disc_quote(const std::string &book,double sales_price,std::size_t qty,double disc):Quote(book,sales_price),quantity(qty),discount(disc) {}virtual double net_price(std::size_t n) const=0;virtual std::string debug() const override{return Quote::debug()+"\n"+"quantity="+std::to_string(quantity)+"\n"+"discount="+std::to_string(discount);}protected:std::size_t quantity=0;double discount=0.0;
};
double print_total(std::ostream &os,const Quote &item,std::size_t n);
class Bulk_quote:public Disc_quote
{public:Bulk_quote()=default;
/*见此处*/	using Disc_quote::Disc::quote;virtual double net_price(std::size_t n) const override{if(n>=quantity)return n*(1-discount)*price;elsereturn n*price;}
};
class Limit_quote:public Disc_quote
{public:Limit_quote()=default;
/*见此处*/	using Disc_quote::Disc::quote;virtual double net_price(std::size_t n) const override{if(n<=quantity)return n*(1-discount)*price;elsereturn quantity*(1-discount)*price+(n-quantity)*price;}
};
#endif

15.28

test.cpp

#include <iostream>
#include <vector>
#include <memory>
#include "Quote.h"
using namespace std;
int main(void)
{/*15.28*/vector<Quote> Qvec;Qvec.push_back(Quote("10-100-111",20));Qvec.push_back(Bulk_quote("11-100-222",30,5,0.2));cout<<Qvec[0].net_price(10)+Qvec[1].net_price(10)<<endl;/*15.29*/vector<shared_ptr<Quote>> Qpvec;Qpvec.push_back(make_shared<Quote>("10-100-111",20));Qpvec.push_back(make_shared<Bulk_quote>("11-100-222",30,5,0.2));cout<<Qpvec[0]->net_price(10)+Qpvec[1]->net_price(10)<<endl;return 0;
}

15.29

见15.28
 不一致,原因在于第一次的vector中所有的元素都是Quote类,即使传入的是Bulk_quote,它也是被忽略掉派生类部分,然后保存到一个Quote类中。而第二次vector由于保存的是基类的只能指针,所以指向的对象既有可能是基类,也有可能是派生类,如此一来在调用net_price时就可以调用到派生类的函数版本。

15.30

Quote.h

#ifndef _QUOTE_H
#define _QUOTE_H
#include <set>
#include <iostream>
#include <string>
#include <memory>
class Quote
{public:Quote()=default;Quote(const std::string &book,double sales_price):price(sales_price),bookNo(book) {}std::string isbn() const {return bookNo;}virtual double net_price(std::size_t n) const {return n*price;}virtual std::string debug() const {return "bookNo="+bookNo+"\n"+"price="+std::to_string(price);}virtual Quote * clone() const & {return new Quote(*this);}virtual Quote * clone() && {return new Quote(std::move(*this));}virtual ~Quote()=default;protected:double price=0.0;private:std::string bookNo;
};
class Disc_quote:public Quote
{public:Disc_quote()=default;Disc_quote(const std::string &book,double sales_price,std::size_t qty,double disc):Quote(book,sales_price),quantity(qty),discount(disc) {}virtual double net_price(std::size_t n) const=0;virtual std::string debug() const override{return Quote::debug()+"\n"+"quantity="+std::to_string(quantity)+"\n"+"discount="+std::to_string(discount);}protected:std::size_t quantity=0;double discount=0.0;
};
double print_total(std::ostream &os,const Quote &item,std::size_t n);
class Bulk_quote:public Disc_quote
{public:Bulk_quote()=default;Bulk_quote(const std::string &book,double sales_price,std::size_t qty,double disc):Disc_quote(book,sales_price,qty,disc) {}virtual double net_price(std::size_t n) const override{if(n>=quantity)return n*(1-discount)*price;elsereturn n*price;}Bulk_quote * clone() const & {return new Bulk_quote(*this);}Bulk_quote * clone() && {return new Bulk_quote(std::move(*this));}
};
class Limit_quote:public Disc_quote
{public:Limit_quote()=default;Limit_quote(const std::string &book,double sales_price,std::size_t qty,double disc):Disc_quote(book,sales_price,qty,disc) {}virtual double net_price(std::size_t n) const override{if(n<=quantity)return n*(1-discount)*price;elsereturn quantity*(1-discount)*price+(n-quantity)*price;}
};
class basket
{public:void add_item(const Quote &sale) {items.insert(std::shared_ptr<Quote>(sale.clone()));}void add_item(Quote &&sale) {items.insert(std::shared_ptr<Quote>(std::move(sale).clone()));}double total_receipt(std::ostream &os) const{double sum=0.0;for(std::multiset<std::shared_ptr<Quote>,decltype(compare) *>::const_iterator iter=items.cbegin();iter!=items.cend();iter=items.upper_bound(*iter))sum+=print_total(os,**iter,items.count(*iter));os<<"Total Sale: "<<sum<<std::endl;return sum;}private:static bool compare(const std::shared_ptr<Quote> &,const std::shared_ptr<Quote> &);std::multiset<std::shared_ptr<Quote>,decltype(compare) *> items{compare};
};
#endif

Quote.cpp

#include "Quote.h"
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;
}
bool basket::compare(const std::shared_ptr<Quote> &lhs,const std::shared_ptr<Quote> &rhs)
{return lhs->isbn()<rhs->isbn();
}

test.cpp

#include <iostream>
#include <vector>
#include <memory>
#include "Quote.h"
using namespace std;
int main(void)
{basket bsk;bsk.add_item(Quote("10-100-111",20));bsk.add_item(Bulk_quote("11-100-222",30,5,0.2));bsk.add_item(Bulk_quote("11-100-222",30,5,0.2));bsk.total_receipt(cout);return 0;
}

15.31

Query
NotQuery
OrQuery
WordQuery1
WordQuery2

同上
3.

Query1
WordQuery2
OrQuery3
WordQuery4
AndQuery5
WordQuery6
WordQuery7

15.32

 因为Query类未定义自己的控制成员函数,并且其只有一个shared_ptr类型的数据成员,所以Query类型的对象被拷贝、移动、赋值或销毁时,会调用shared_ptr类型相应的控制成员。

15.33

 因为Query_base类是一个抽象基类,我们不能直接创建一个抽象基类的对象,实际上在它的派生类对象被创建时,它才会作为其基类部分被创建。同时它没有定义控制成员函数,又不含数据成员,所以它在被拷贝、移动、赋值或销毁时会执行默认语义,什么都不做。

15.34

WordQuery(const std::string &) → \rightarrow fiery
Query(const std::string &) → \rightarrow fiery
WordQuery(const std::string &) → \rightarrow bird
Query(const std::string &) → \rightarrow bird
BinaryQuery(const Query &,const Query &,std::string) → \rightarrow (fiery,bird,&)
AndQuery(const Query &,const Query &) → \rightarrow (fiery,bird)
Query(std::shared_ptr<Query_base>)
WordQuery(const std::string &) → \rightarrow wind
Query(const std::string &) → \rightarrow wind
BinaryQuery(const Query &,const Query &,std::string) → \rightarrow ((fiery & bird),wind,|)
OrQuery(const Query &,const Query &) → \rightarrow ((fiery & bird),wind)
Query(std::shared_ptr<Query_base>)
2.
Query::rep
BinaryQuery::rep
Query::rep
WordQuery::rep
Query::rep
BinaryQuery::rep
Query::rep
WordQuery::rep
Query::rep
WordQuery::rep
3.
Query::eval
OrQuery::eval
Query::eval
WordQuery::eval
Query::eval
AndQuery::eval
Query::eval
WordQuery::eval
Query::eval
WordQuery::eval

15.35

class Query_base
{friend class Query;protected:using line_no=TextQuery::line_no;virtual ~Query_base()=default;private:virtual QueryResult eval(const TextQuery &) const=0;virtual std::string rep() const=0;
};
class Query
{friend Query operator~(const Query &);friend Query operator&(const Query &,const Query &);friend Query operator|(const Query &,const Query &);public:Query(const std::string &);QueryResult eval(const TextQuery &t) const {return q->eval(t);}std::string rep() const {return q->rep();}private:Query(std::shared_ptr<Query_base> query):q(query) {}std::shared_ptr<Query_base> q;
};

15.36

参考15.39自行添加打印语句

15.37

 仅把派生类中的Query类型数据成员改成**shared_ptr<Query_base>**类型成员的话,影响并不大,因为Query类本来就有接受智能指针的构造函数,必要的地方手动类型转换即可。

15.38

  • 不合法,不能直接创建抽象基类的对象。
  • 不合法,AndQuery没有接受Query参数的构造函数。
  • 不合法,OrQuery没有接受Query参数的构造函数。

15.39

Query.h

#ifndef _QUERY_H
#define _QUERY_H
#include <iostream>
#include <string>
#include <vector>
#include <map>
#include <set>
#include <memory>
#include <fstream>
class QueryResult;
class TextQuery
{public:using line_no=std::vector<std::string>::size_type;TextQuery(std::ifstream &);QueryResult query(const std::string &) const;private:std::shared_ptr<std::vector<std::string>> file;std::map<std::string,std::shared_ptr<std::set<line_no>>> wm;
};
class QueryResult
{friend std::ostream &print(std::ostream &,const QueryResult &);public:QueryResult(std::string s,std::shared_ptr<std::set<std::vector<std::string>::size_type>> l,std::shared_ptr<std::vector<std::string>> f):sought(s),lines(l),file(f){}std::set<std::vector<std::string>::size_type>::iterator begin() const {return lines->begin();}std::set<std::vector<std::string>::size_type>::iterator end() const {return lines->end();}std::shared_ptr<std::vector<std::string>> get_file(){return file;}private:std::string sought;std::shared_ptr<std::set<std::vector<std::string>::size_type>> lines;std::shared_ptr<std::vector<std::string>> file;
};
std::ostream &print(std::ostream &,const QueryResult &);
inline std::string make_plural(std::size_t count,const std::string &word,const std::string &ending)
{return (count>1)?word+ending:word;
}
class Query_base
{friend class Query;protected:using line_no=TextQuery::line_no;virtual ~Query_base()=default;private:virtual QueryResult eval(const TextQuery &) const=0;virtual std::string rep() const=0;
};
class Query
{friend Query operator~(const Query &);friend Query operator&(const Query &,const Query &);friend Query operator|(const Query &,const Query &);public:Query(const std::string &);QueryResult eval(const TextQuery &t) const {return q->eval(t);}std::string rep() const {return q->rep();}private:Query(std::shared_ptr<Query_base> query):q(query) {}std::shared_ptr<Query_base> q;
};
class WordQuery:public Query_base
{friend class Query;private:WordQuery(const std::string &s):query_word(s) {}virtual QueryResult eval(const TextQuery &t) const {return t.query(query_word);}virtual std::string rep() const {return query_word;}std::string query_word;
};inline Query::Query(const std::string &s):q(new WordQuery(s)) {}class NotQuery:public Query_base
{friend Query operator~(const Query &);private:NotQuery(const Query &q):query(q) {}virtual QueryResult eval(const TextQuery &) const;virtual std::string rep() const {return "~("+query.rep()+")";}Query query;
};
inline Query operator~(const Query &q) {return std::shared_ptr<Query_base>(new NotQuery(q));}
class BinaryQuery:public Query_base
{protected:BinaryQuery(const Query &left,const Query &right,const std::string &s):lhs(left),rhs(right),opSym(s) {}virtual std::string rep() const {return "("+lhs.rep()+" "+opSym+" "+rhs.rep()+")";}Query lhs,rhs;std::string opSym;
};
class AndQuery:public BinaryQuery
{friend Query operator&(const Query&,const Query&);private:AndQuery(const Query &left,const Query &right):BinaryQuery(left,right,"&") {}virtual QueryResult eval(const TextQuery &) const;
};
inline Query operator&(const Query &left,const Query &right) {return std::shared_ptr<Query_base>(new AndQuery(left,right));}
class OrQuery:public BinaryQuery
{friend Query operator|(const Query &,const Query &);private:OrQuery(const Query &left,const Query &right):BinaryQuery(left,right,"|") {}virtual QueryResult eval(const TextQuery &) const;
};
inline Query operator|(const Query &left,const Query &right) {return std::shared_ptr<Query_base>(new OrQuery(left,right));}
inline std::ostream & operator<<(std::ostream &os,const Query &q) {return os<<q.rep();}
#endif

Query.cpp

#include <sstream>
#include <algorithm>
#include <cctype>
#include "Query.h"
TextQuery::TextQuery(std::ifstream &infile):file(new std::vector<std::string>)
{std::string text;while(getline(infile,text)){file->push_back(text);std::size_t line_number=file->size()-1;std::istringstream line(text);std::string word;while(line>>word){std::string key_word;for(auto c:word){if(!ispunct(c))key_word+=c;}std::shared_ptr<std::set<line_no>> &lines=wm[key_word];if(!lines)lines.reset(new std::set<line_no>);lines->insert(line_number);}}
}
QueryResult TextQuery::query(const std::string &sought) const
{static std::shared_ptr<std::set<line_no>> nodata(new std::set<line_no>);std::map<std::string,std::shared_ptr<std::set<line_no>>>::const_iterator map_it=wm.find(sought);if(map_it==wm.end())return QueryResult(sought,nodata,file);elsereturn QueryResult(sought,map_it->second,file);
}std::ostream &print(std::ostream &os,const QueryResult &qr)
{os<<"Executing Query for: "<<qr.sought<<std::endl;os<<qr.sought<<" occurs "<<qr.lines->size()<<" "<<make_plural(qr.lines->size(),"time","s")<<std::endl;for(auto num:*(qr.lines))os<<"\t(line "<<num+1<<") "<<*(qr.file->begin()+num)<<std::endl;return os;
}
QueryResult NotQuery::eval(const TextQuery &text) const
{auto result=query.eval(text);auto beg=result.begin(),end=result.end();auto ret_lines=std::make_shared<std::set<line_no>>();auto sz=result.get_file()->size();for(std::size_t n=0;n!=sz;++n){if(beg==end||*beg!=n)ret_lines->insert(n);else if(beg!=end)++beg;}return QueryResult(rep(),ret_lines,result.get_file());
}
QueryResult OrQuery::eval(const TextQuery &text) const
{auto left=lhs.eval(text),right=rhs.eval(text);auto ret_lines=std::make_shared<std::set<line_no>>(left.begin(),left.end());ret_lines->insert(right.begin(),right.end());return QueryResult(rep(),ret_lines,left.get_file());
}
QueryResult AndQuery::eval(const TextQuery &text) const
{auto left=lhs.eval(text),right=rhs.eval(text);auto ret_lines=std::make_shared<std::set<line_no>>();set_intersection(left.begin(),left.end(),right.begin(),right.end(),inserter(*ret_lines,ret_lines->begin()));return QueryResult(rep(),ret_lines,left.get_file());
}

test.cpp

#include <fstream>
#include "Query.h"
using namespace std;
int main(int argc,char *argv[])
{ifstream infile(argv[1]);TextQuery text(infile);Query q=Query("fiery")&Query("bird")|Query("wind");print(cout,q.eval(text));return 0;
}

15.40

set的构造函数和insert成员函数都可以正确处理空范围的情况,这种情况下得到的QueryResultlines成员指向的set也将是空的。

15.41

Query.h

#ifndef _QUERY_H
#define _QUERY_H
#include <iostream>
#include <string>
#include <vector>
#include <map>
#include <set>
#include <memory>
#include <fstream>
class QueryResult;
class TextQuery
{public:using line_no=std::vector<std::string>::size_type;TextQuery(std::ifstream &);QueryResult query(const std::string &) const;private:std::shared_ptr<std::vector<std::string>> file;std::map<std::string,std::shared_ptr<std::set<line_no>>> wm;
};
class QueryResult
{friend std::ostream &print(std::ostream &,const QueryResult &);public:QueryResult(std::string s,std::shared_ptr<std::set<std::vector<std::string>::size_type>> l,std::shared_ptr<std::vector<std::string>> f):sought(s),lines(l),file(f){}std::set<std::vector<std::string>::size_type>::iterator begin() const {return lines->begin();}std::set<std::vector<std::string>::size_type>::iterator end() const {return lines->end();}std::shared_ptr<std::vector<std::string>> get_file(){return file;}private:std::string sought;std::shared_ptr<std::set<std::vector<std::string>::size_type>> lines;std::shared_ptr<std::vector<std::string>> file;
};
std::ostream &print(std::ostream &,const QueryResult &);
inline std::string make_plural(std::size_t count,const std::string &word,const std::string &ending)
{return (count>1)?word+ending:word;
}
class Query_base
{friend class Query;protected:using line_no=TextQuery::line_no;virtual ~Query_base()=default;private:virtual QueryResult eval(const TextQuery &) const=0;virtual std::string rep() const=0;
};
class Query
{friend Query operator~(const Query &);friend Query operator&(const Query &,const Query &);friend Query operator|(const Query &,const Query &);public:Query(const std::string &);Query(const Query &rhs):q(rhs.q),reference_count(rhs.reference_count) {++*reference_count;}Query & operator=(const Query &);~Query();QueryResult eval(const TextQuery &t) const {return q->eval(t);}std::string rep() const {return q->rep();}private:Query(Query_base *query):q(query),reference_count(new std::size_t(1)) {}Query_base *q;std::size_t *reference_count;
};
class WordQuery:public Query_base
{friend class Query;private:WordQuery(const std::string &s):query_word(s) {}virtual QueryResult eval(const TextQuery &t) const {return t.query(query_word);}virtual std::string rep() const {return query_word;}std::string query_word;
};inline Query::Query(const std::string &s):q(new WordQuery(s)),reference_count(new std::size_t(1)) {}class NotQuery:public Query_base
{friend Query operator~(const Query &);private:NotQuery(const Query &q):query(q) {}virtual QueryResult eval(const TextQuery &) const;virtual std::string rep() const {return "~("+query.rep()+")";}Query query;
};
inline Query operator~(const Query &q) {return new NotQuery(q);}
class BinaryQuery:public Query_base
{protected:BinaryQuery(const Query &left,const Query &right,const std::string &s):lhs(left),rhs(right),opSym(s) {}virtual std::string rep() const {return "("+lhs.rep()+" "+opSym+" "+rhs.rep()+")";}Query lhs,rhs;std::string opSym;
};
class AndQuery:public BinaryQuery
{friend Query operator&(const Query&,const Query&);private:AndQuery(const Query &left,const Query &right):BinaryQuery(left,right,"&") {}virtual QueryResult eval(const TextQuery &) const;
};
inline Query operator&(const Query &left,const Query &right) {return new AndQuery(left,right);}
class OrQuery:public BinaryQuery
{friend Query operator|(const Query &,const Query &);private:OrQuery(const Query &left,const Query &right):BinaryQuery(left,right,"|") {}virtual QueryResult eval(const TextQuery &) const;
};
inline Query operator|(const Query &left,const Query &right) {return new OrQuery(left,right);}
inline std::ostream & operator<<(std::ostream &os,const Query &q) {return os<<q.rep();}
#endif

Query.cpp

#include <sstream>
#include <algorithm>
#include <cctype>
#include "Query.h"
TextQuery::TextQuery(std::ifstream &infile):file(new std::vector<std::string>)
{std::string text;while(getline(infile,text)){file->push_back(text);std::size_t line_number=file->size()-1;std::istringstream line(text);std::string word;while(line>>word){std::string key_word;for(auto c:word){if(!ispunct(c))key_word+=c;}std::shared_ptr<std::set<line_no>> &lines=wm[key_word];if(!lines)lines.reset(new std::set<line_no>);lines->insert(line_number);}}
}
QueryResult TextQuery::query(const std::string &sought) const
{static std::shared_ptr<std::set<line_no>> nodata(new std::set<line_no>);std::map<std::string,std::shared_ptr<std::set<line_no>>>::const_iterator map_it=wm.find(sought);if(map_it==wm.end())return QueryResult(sought,nodata,file);elsereturn QueryResult(sought,map_it->second,file);
}std::ostream &print(std::ostream &os,const QueryResult &qr)
{os<<"Executing Query for: "<<qr.sought<<std::endl;os<<qr.sought<<" occurs "<<qr.lines->size()<<" "<<make_plural(qr.lines->size(),"time","s")<<std::endl;for(auto num:*(qr.lines))os<<"\t(line "<<num+1<<") "<<*(qr.file->begin()+num)<<std::endl;return os;
}
Query & Query::operator=(const Query &rhs)
{++*rhs.reference_count;if(--*reference_count==0){delete q;delete reference_count;}q=rhs.q;reference_count=rhs.reference_count;return *this;
}
Query::~Query()
{if(--*reference_count==0){delete q;delete reference_count;}
}
QueryResult NotQuery::eval(const TextQuery &text) const
{auto result=query.eval(text);auto beg=result.begin(),end=result.end();auto ret_lines=std::make_shared<std::set<line_no>>();auto sz=result.get_file()->size();for(std::size_t n=0;n!=sz;++n){if(beg==end||*beg!=n)ret_lines->insert(n);else if(beg!=end)++beg;}return QueryResult(rep(),ret_lines,result.get_file());
}
QueryResult OrQuery::eval(const TextQuery &text) const
{auto left=lhs.eval(text),right=rhs.eval(text);auto ret_lines=std::make_shared<std::set<line_no>>(left.begin(),left.end());ret_lines->insert(right.begin(),right.end());return QueryResult(rep(),ret_lines,left.get_file());
}
QueryResult AndQuery::eval(const TextQuery &text) const
{auto left=lhs.eval(text),right=rhs.eval(text);auto ret_lines=std::make_shared<std::set<line_no>>();set_intersection(left.begin(),left.end(),right.begin(),right.end(),inserter(*ret_lines,ret_lines->begin()));return QueryResult(rep(),ret_lines,left.get_file());
}

15.42

按句子查询并打印单词,而不再是按行打印。
Query.h

#ifndef _QUERY_H
#define _QUERY_H
#include <iostream>
#include <string>
#include <vector>
#include <map>
#include <set>
#include <memory>
#include <fstream>
class QueryResult;
class TextQuery
{public:using line_no=std::vector<std::string>::size_type;TextQuery(std::ifstream &);QueryResult query(const std::string &) const;private:std::shared_ptr<std::vector<std::string>> file;std::map<std::string,std::shared_ptr<std::set<line_no>>> wm;
};
class QueryResult
{friend std::ostream &print(std::ostream &,const QueryResult &);public:QueryResult(std::string s,std::shared_ptr<std::set<std::vector<std::string>::size_type>> l,std::shared_ptr<std::vector<std::string>> f):sought(s),lines(l),file(f){}std::set<std::vector<std::string>::size_type>::iterator begin() const {return lines->begin();}std::set<std::vector<std::string>::size_type>::iterator end() const {return lines->end();}std::shared_ptr<std::vector<std::string>> get_file(){return file;}private:std::string sought;std::shared_ptr<std::set<std::vector<std::string>::size_type>> lines;std::shared_ptr<std::vector<std::string>> file;
};
std::ostream &print(std::ostream &,const QueryResult &);
inline std::string make_plural(std::size_t count,const std::string &word,const std::string &ending)
{return (count>1)?word+ending:word;
}
class Query_base
{friend class Query;protected:using line_no=TextQuery::line_no;virtual ~Query_base()=default;private:virtual QueryResult eval(const TextQuery &) const=0;virtual std::string rep() const=0;
};
class Query
{friend Query operator~(const Query &);friend Query operator&(const Query &,const Query &);friend Query operator|(const Query &,const Query &);public:Query(const std::string &);Query(const Query &rhs):q(rhs.q),reference_count(rhs.reference_count) {++*reference_count;}Query & operator=(const Query &);~Query();QueryResult eval(const TextQuery &t) const {return q->eval(t);}std::string rep() const {return q->rep();}private:Query(Query_base *query):q(query),reference_count(new std::size_t(1)) {}Query_base *q;std::size_t *reference_count;
};
class WordQuery:public Query_base
{friend class Query;private:WordQuery(const std::string &s):query_word(s) {}virtual QueryResult eval(const TextQuery &t) const {return t.query(query_word);}virtual std::string rep() const {return query_word;}std::string query_word;
};inline Query::Query(const std::string &s):q(new WordQuery(s)),reference_count(new std::size_t(1)) {}class NotQuery:public Query_base
{friend Query operator~(const Query &);private:NotQuery(const Query &q):query(q) {}virtual QueryResult eval(const TextQuery &) const;virtual std::string rep() const {return "~("+query.rep()+")";}Query query;
};
inline Query operator~(const Query &q) {return new NotQuery(q);}
class BinaryQuery:public Query_base
{protected:BinaryQuery(const Query &left,const Query &right,const std::string &s):lhs(left),rhs(right),opSym(s) {}virtual std::string rep() const {return "("+lhs.rep()+" "+opSym+" "+rhs.rep()+")";}Query lhs,rhs;std::string opSym;
};
class AndQuery:public BinaryQuery
{friend Query operator&(const Query&,const Query&);private:AndQuery(const Query &left,const Query &right):BinaryQuery(left,right,"&") {}virtual QueryResult eval(const TextQuery &) const;
};
inline Query operator&(const Query &left,const Query &right) {return new AndQuery(left,right);}
class OrQuery:public BinaryQuery
{friend Query operator|(const Query &,const Query &);private:OrQuery(const Query &left,const Query &right):BinaryQuery(left,right,"|") {}virtual QueryResult eval(const TextQuery &) const;
};
inline Query operator|(const Query &left,const Query &right) {return new OrQuery(left,right);}
inline std::ostream & operator<<(std::ostream &os,const Query &q) {return os<<q.rep();}
#endif

Query.cpp

#include <sstream>
#include <algorithm>
#include <cctype>
#include "Query.h"
TextQuery::TextQuery(std::ifstream &infile):file(new std::vector<std::string>)
{std::string text;while(getline(infile,text,'.')){for(decltype(text.size()) index=0;index!=text.size();++index){if(text[index]=='\n')text[index]=' ';}file->push_back(text);std::size_t line_number=file->size()-1;std::istringstream line(text);std::string word;while(line>>word){std::string key_word;for(auto c:word){if(!ispunct(c))key_word+=c;}std::shared_ptr<std::set<line_no>> &lines=wm[key_word];if(!lines)lines.reset(new std::set<line_no>);lines->insert(line_number);}}
}
QueryResult TextQuery::query(const std::string &sought) const
{static std::shared_ptr<std::set<line_no>> nodata(new std::set<line_no>);std::map<std::string,std::shared_ptr<std::set<line_no>>>::const_iterator map_it=wm.find(sought);if(map_it==wm.end())return QueryResult(sought,nodata,file);elsereturn QueryResult(sought,map_it->second,file);
}std::ostream &print(std::ostream &os,const QueryResult &qr)
{os<<"Executing Query for: "<<qr.sought<<std::endl;os<<qr.sought<<" occurs "<<qr.lines->size()<<" "<<make_plural(qr.lines->size(),"time","s")<<std::endl;for(auto num:*(qr.lines))os<<"\t(sentence "<<num+1<<") "<<*(qr.file->begin()+num)<<"."<<std::endl;return os;
}
Query & Query::operator=(const Query &rhs)
{++*rhs.reference_count;if(--*reference_count==0){delete q;delete reference_count;}q=rhs.q;reference_count=rhs.reference_count;return *this;
}
Query::~Query()
{if(--*reference_count==0){delete q;delete reference_count;}
}
QueryResult NotQuery::eval(const TextQuery &text) const
{auto result=query.eval(text);auto beg=result.begin(),end=result.end();auto ret_lines=std::make_shared<std::set<line_no>>();auto sz=result.get_file()->size();for(std::size_t n=0;n!=sz;++n){if(beg==end||*beg!=n)ret_lines->insert(n);else if(beg!=end)++beg;}return QueryResult(rep(),ret_lines,result.get_file());
}
QueryResult OrQuery::eval(const TextQuery &text) const
{auto left=lhs.eval(text),right=rhs.eval(text);auto ret_lines=std::make_shared<std::set<line_no>>(left.begin(),left.end());ret_lines->insert(right.begin(),right.end());return QueryResult(rep(),ret_lines,left.get_file());
}
QueryResult AndQuery::eval(const TextQuery &text) const
{auto left=lhs.eval(text),right=rhs.eval(text);auto ret_lines=std::make_shared<std::set<line_no>>();set_intersection(left.begin(),left.end(),right.begin(),right.end(),inserter(*ret_lines,ret_lines->begin()));return QueryResult(rep(),ret_lines,left.get_file());
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/732572.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

C#实现快速排序算法

C#实现快速排序算法 以下是C#中的快速排序算法实现示例&#xff1a; using System;class QuickSort {// 快速排序入口函数public static void Sort(int[] array){QuickSortRecursive(array, 0, array.Length - 1);}// 递归函数实现快速排序private static void QuickSortRecu…

springboot配置Redis缓存多节点

随着微服务架构的广泛应用&#xff0c;分布式缓存系统在提升系统性能、降低数据库压力方面起着关键作用。Redis作为高性能的内存键值对数据库&#xff0c;凭借其丰富的数据结构和高速读写能力&#xff0c;在众多缓存解决方案中脱颖而出。在Spring Boot框架中&#xff0c;我们可…

Python 潮流周刊第 41 期(摘要),赠书5本

本周刊由 Python猫 出品&#xff0c;精心筛选国内外的 250 信息源&#xff0c;为你挑选最值得分享的文章、教程、开源项目、软件工具、播客和视频、热门话题等内容。愿景&#xff1a;帮助所有读者精进 Python 技术&#xff0c;并增长职业和副业的收入。 周刊全文&#xff1a;h…

测试开发面试题|面试真题

📋 个人简介 作者简介:大家好,我是凝小飞,软件测试领域作者支持我:点赞👍+收藏⭐️+留言📝测试开发的面试题,一般会考一些基础的算法编程题,难度不是特别高,除非是大厂的那种卷,如下是我作为面试官整理的一些参考测试题,供参考 算法排序类 Python: 一、list…

ubuntu自带屏幕截图功能

目录 简介开始截屏步骤1.打开截屏软件2.选择区域3.截图 快捷键 录屏方法11.开始录屏2.停止录屏 方法2 补充说明 简介 试了好多开源跨平台截图软件&#xff0c;但是在ubuntu上都或多或少存在问题。ubuntu有自带的截图软件。打算把ubuntu自带的截图软件用起来。 顺便说一下我使…

B端系统升级,登录页必在升级之列,不容置疑。

进行B端界面升级时&#xff0c;首先升级登录页有以下几个原因&#xff1a; 用户体验&#xff1a;登录页是用户进入系统的第一个页面&#xff0c;用户首先接触到的界面。通过升级登录页&#xff0c;可以提升用户的第一印象&#xff0c;增强用户对系统的信任感和好感度&#xff…

Android Studio编译及调试知识

文章目录 Android Studio编译kotlin项目Android Studio编译Java和kotlin混合项目的过程gradle打印详细错误信息&#xff0c;类似这种工具的使用Android apk 从你的代码到APK打包的过程&#xff0c;APK安装到你的Android手机上的过程&#xff0c;最后安装好的形态&#xff0c;以…

简单形状点云轮廓点排序(旋转角)

1、背景介绍 很多边缘提取算法提取的边缘点为无序点云&#xff0c;如下图所示&#xff0c;无序点云不利于后续各种应用&#xff0c;比如根据边缘计算点云面积、点云轮廓线规则化等。若对点云进行排序&#xff0c;则可以进行上述引用。但实际上&#xff0c;点云形状错综复杂&…

Dubbo 和 Zookeeper 的关系

Dubbo 和 Zookeeper 的关系 Zookeeper的作用 zookeeper用来注册服务和进行负载均衡&#xff0c;哪一个服务由哪一个机器来提供必需让调用者知道&#xff0c;简 单来说就是ip地址和服务名称的对应关系。当然也可以通过硬编码的方式把这种对应关系在调用方 业务代码中实现&#…

蓝桥杯第十四届真题 棋盘 二维差分数组

题目 小蓝拥有 nn 大小的棋盘&#xff0c;一开始棋盘上全都是白子。 小蓝进行了 m 次操作&#xff0c;每次操作会将棋盘上某个范围内的所有棋子的颜色取反(也就是白色棋子变为黑色&#xff0c;黑色棋子变为白色)。 请输出所有操作做完后棋盘上每个棋子的颜色。 输入格式 输…

AVL树讲解

AVL树 1. 概念2. AVL节点的定义3. AVL树插入3.1 旋转 4.AVL树的验证 1. 概念 AVL树是一种自平衡二叉搜索树。它的每个节点的左子树和右子树的高度差&#xff08;平衡因子&#xff0c;我们这里按右子树高度减左子树高度&#xff09;的绝对值不超过1。AVL的左子树和右子树都是AV…

P8651 [蓝桥杯 2017 省 B] 日期问题---洛谷(题解)

这周周赛的题&#xff0c;我感觉我这题写的还是不错的&#xff0c;用到了上周周赛的口算题中别人题解的函数和最近了解substr还有去年天梯校赛有个日期检验的题&#xff0c;都有用到。 题目描述 小明正在整理一批历史文献。这些历史文献中出现了很多日期。小明知道这些日期都…

Rust 语言中的泛型

在Rust中&#xff0c;泛型&#xff08;Generics&#xff09;是一种允许你编写与多种不同数据类型一起工作的代码的方式。Rust主要通过两种方式来支持泛型&#xff1a;使用泛型函数和泛型结构体。下面是一些使用Rust泛型的示例。 一、泛型函数示例 fn add<T>(x: T, y: T…

MIT6.5840(6.824)Lab2总结(Raft)

MIT6.5840&#xff08;原MIT6.824&#xff09;Lab2总结&#xff08;Raft&#xff09; 资源分享&#xff1a; 官网地址&#xff1a;http://nil.csail.mit.edu/6.5840/2023/ Raft论文地址&#xff1a;http://nil.csail.mit.edu/6.5840/2023/papers/raft-extended.pdf 官方学生…

学习笔记 反悔贪心

0.写在前面 好久没更了&#xff0c;这周是开学第一周 A C M ACM ACM队临时安排讲课任务&#xff0c;没人讲&#xff0c;我就揽下来这活了。前两天有一道 c f cf cf的 d i v 2 C div2C div2C用到了反悔贪心这个技巧&#xff0c;也不需要什么前置算法就可以学&#xff0c;所以我…

JAVA循环中标记的作用

在Java循环中标记的作用是为循环语句提供一个标识符&#xff0c;使得程序可以在循环嵌套时跳出指定的循环。它可以用于在内部循环中控制外部循环&#xff0c;或者在多个嵌套循环中控制跳出特定的循环块。 标记通常与break和continue语句一起使用。使用break语句配合标记可以跳…

CentOS上安装与配置Nginx

CentOS上安装与配置Nginx Nginx是一款轻量级的Web服务器/反向代理服务器及电子邮件&#xff08;IMAP/POP3&#xff09;代理服务器&#xff0c;并在一个BSD-like协议下发行。以下是在CentOS系统上安装和配置Nginx的步骤。 &#x1f31f; 前言 欢迎来到我的小天地&#xff0c;这…

在深度学习中,时间、空间、通道三个维度是什么?

在深度学习中&#xff0c;时间、空间、通道三个维度是什么&#xff1f; 在深度学习中&#xff0c;时间、空间和通道是描述输入数据的三个主要维度。 空间维度&#xff08;Spatial Dimension&#xff09;&#xff1a; 指的是输入数据在空间中的排列方式。对于图像数据来说&…

Web Servlet

目录 1 简介2 创建Servlet项目并成功发布运行3 新加Servlet步骤4 Servlet项目练习5 Servlet运行原理6 操作 HTTP Request头的方法(部分方法示例)7 操作 HTTP Response头的方法(部分方法示例)8 两种重定向(页面跳转)方法9 Cookie9.1 Cookie工作原理9.2 cookie构成9.3 Servlet 操…

Java并发包中的ConcurrentLinkedQueue与LinkedBlockingQueue深度对比

Java并发包中的ConcurrentLinkedQueue与LinkedBlockingQueue深度对比 在Java的并发编程中&#xff0c;队列是一种非常重要的数据结构&#xff0c;它们提供了线程安全的数据共享方式。java.util.concurrent包中提供了多种并发队列&#xff0c;其中ConcurrentLinkedQueue和Linke…