部分习题解答:
15.1:
虚成员即为虚函数
15.2:
protected受保护的成员,其派生类可以访问其成员;而private私有成员,其派生类不可以访问
15.3:
#ifndef QUOTE_H
#define QUOTE_H
#include <iostream>
#include <string>
using namespace std;
class Quote {
public:
Quote() = default;
Quote(const string &book,double sales_price):
bookNo(book),price(sales_price){}
string isbn() const { return bookNo; }
virtual double net_price(size_t n) const
{
return n * price;
}
virtual ~Quote() = default;
private:
string bookNo;
protected :
double price = 0.0;
};
double print_total(ostream &os, const Quote &item, size_t n)
{
double ret = item.net_price(n);
os << "ISBN: " << item.isbn()
<< " # sold: " << n << " total due: " << ret << endl;
return ret;
}
#endif // ! QUOTE_H
15.4:
(a)错误,类不能继承自身
(b)正确
(c)派生类的声明中包含类名但不能包含它的派生列表
15.5、15.6:
#ifndef QUOTE_H
#define QUOTE_H
#include <iostream>
#include <string>
using namespace std;
class Quote {
public:
Quote() = default;
Quote(const string &book,double sales_price):
bookNo(book),price(sales_price){}
string isbn() const { return bookNo; }
virtual double net_price(size_t n) const
{
return n * price;
}
virtual ~Quote() = default;
private:
string bookNo;
protected :
double price = 0.0;
};
double print_total(ostream &os, const Quote &item, size_t n)
{
double ret = item.net_price(n);
os << "ISBN: " << item.isbn()
<< " # sold: " << n << " total due: " << ret << endl;
return ret;
}
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) {}
double net_price(size_t cnt) const
{
if (cnt >= min_qty)
return cnt * (1 - discount) * price;
else
return cnt * price;
}
private:
size_t min_qty = 0;
double discount = 0.0;
};
#endif // ! QUOTE_H
//test.cpp
#include <iostream>
#include "Quote.h"
using namespace std;
int main()
{
Quote book1("嫌疑人x的献身", 35.0);
Bulk_quote book2("上海堡垒", 38.0, 10, 0.3);
print_total(cout, book1, 10);
print_total(cout, book2, 10);
system("pause");
return 0;
}
15.7:
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) {}
double net_price(size_t cnt) const
{
if (cnt > min_qty)
return min_qty * (1 - discount) * price + (cnt - min_qty) * price;
else
return cnt * (1 - discount) * price;
}
private:
size_t min_qty = 0;
double discount = 0.0;
};
15.8:
静态类型:变量声明时的类型或表达式生成的类型
动态类型:变量或表达式表示的内存中的对象的类型
15.9:
基类的指针或引用,其静态类型与动态类型不同
15.10:
ifstream从istream派生而来,也是一个输入流对象,所以可以正常使用
15.11:
//Quote类
virtual void debug()
{
cout << "This is Quote Class " << endl;
cout << "ISBN: " << bookNo << endl;
cout << "PRICE: " << price << endl;
}
//Bulk_quote类
void debug()
{
cout << "This is bulk_quote Class" << endl;
cout << "DISCOUNT: " << discount << endl;
cout << "Min_qty: " << min_qty << endl;
cout << "Price: " << price << endl;
}
15.12:
有必要,将成员函数声明成override预防意外,而final可以防止成员函数被后续的覆盖
15.13:
将派生类中的print函数中调用print(os)改为base::print(os)
15.15:
#ifndef DISC_QUOTE_H
#define DISC_QUOTE_H
#include <iostream>
#include <string>
#include "Quote.h"
using namespace std;
class Disc_quote :public Quote{
public:
Disc_quote() = default;
Disc_quote(const string& book, double price, size_t qty, double disc):
Quote(book,price),quantity(qty),discount(disc) {}
double net_price(size_t)const = 0; //纯虚函数
protected:
size_t quantity = 0;
double discount = 0.0;
};
class Bulk_quote :public Disc_quote {
public:
Bulk_quote() = default;
Bulk_quote(const string& book, double p, size_t qty, double disc) :
Disc_quote(book,p,qty,disc) {}
double net_price(size_t cnt) const override
{
if (cnt > quantity)
return cnt * (1 - discount) * price;
else
return cnt * price;
}
};
#endif // !DISC_QUOTE_H
15.16:
class Limit_quote :public Disc_quote {
public:
Limit_quote() = default;
Limit_quote(const string& book, double p, size_t qty, double disc) :
Disc_quote(book,p,qty,disc) {}
double net_price(size_t cnt) const
{
if (cnt > quantity)
return quantity * (1 - discount) * price + (cnt - quantity) * price;
else
return cnt * (1 - discount) * price;
}
};
15.17:
不能实例化抽象类
15.18:
只有d1和dd1才能够赋值。这是因为:只有当派生类公有地继承基类时,用户代码才能使用派生类向基类的转换;也就是说,如果派生类继承基类的方式是受保护的或者私有的,则用户代码不能使用该转换。
在题中,只有d1和dd1类是公有地继承基类,故只有它们才能完成向基类的转换。
15.19:
Derived_from_private : private priv_Derv这个类的函数是不合法的
15.20:
#ifndef BASE_H
#define BASE_H
#include <iostream>
using namespace std;
class Base {
public:
void pub_mem();
protected:
int prot_mem;
private:
char priv_mem;
};
struct Pub_Derv : public Base {
int f() { return prot_mem; }
void memfcn(Base &b)
{
b = *this;
cout << "Pub_Derv" << endl;
}
};
struct Priv_Derv : private Base {
int f1() const { return prot_mem; }
void memfcn(Base &b)
{
b = *this;
cout << "Priv_Derv" << endl;
}
};
struct Prot_Derv : protected Base {
int f2() const { return prot_mem; }
void memfcn(Base &b)
{
b = *this;
cout << "Prov_Derv" << endl;
}
};
struct Derived_from_Public : public Pub_Derv {
int use_base() { return prot_mem; }
void memfcn(Base &b)
{
b = *this;
cout << "Derived_from_Public" << endl;
}
};
struct Derived_from_Protected : protected Pub_Derv {
int use_base() { return prot_mem; }
void memfcn(Base &b)
{
b = *this;
cout << "Derived_from_Protected" << endl;
}
};
#endif // ! BASE_H
//test.cpp
int main(int argc, const char *argv[])
{
Pub_Derv d1;
Priv_Derv d2;
Prot_Derv d3;
Derived_from_Public dd1; //Derived_from_Private dd2;
Derived_from_Protected dd3;
Base base;
Base *p= new Base;
p = &d1;
//p = &d2;
//p = &d3;
p = &dd1;
//p = &dd2;
//p = &dd3;
d1.memfcn(base);
d2.memfcn(base);
d3.memfcn(base);
dd1.memfcn(base);
//d2.memfcn(bade);
dd3.memfcn(base);
return 0;
}
15.21、15.22:
#ifndef FIGURE_H
#define FIGURE_H
class Figure {
public:
Figure(double, double);
protected:
double xSize, ySize;
};
class Figure_2D : public Figure {
public:
Figure_2D(double, double);
virtual double area() = 0;
virtual double pcrimeter() = 0;
};
class Figure_3D : public Figure {
public:
Figure_3D(double, double, double);
virtual double cubage() = 0;
protected:
double zSize;
};
class Rectangle : public Figure_2D {
public:
Rectangle(double, double);
virtual double area();
virtual double pcrimeter();
};
class Circle : public Figure_2D {
public:
Circle(double, double);
virtual double area();
virtual double pcrimeter();
};
class Sphere : public Figure_3D {
public:
Sphere(double, double, double);
virtual double cubage();
};
class Cone : public Figure_3D {
public:
Cone(double, double, double);
virtual double cubage();
};
#endif // ! FIGURE_H
15.23:
应改为:
int fcn();
如果修改了fcn匹配Base中的定义,则只有虚函数调用将存在,fcn(int)的调用将错误
15.24:
基类需要虚析构函数; 动态销毁对象
15.25:
因为Disc_quote的默认构造函数会运行Quote的默认构造函数,而Quote默认构造函数会完成成员的初始化工作。
如果去掉该函数的话,Bulk_quote的默认构造函数无法完成Disc_quote的初始化工作。
15.26;
#ifndef QUOTE_H
#define QUOTE_H
#include <iostream>
#include <string>
using namespace std;
class Quote {
friend double print_total(ostream &os, const Quote &item, size_t n);
friend bool operator != (const Quote& rhs, const Quote& rhs1);
public:
Quote() = default;
Quote(const string &book,double sales_price):
bookNo(book),price(sales_price){}
Quote(const Quote& quote1) : bookNo(quote1.bookNo), price(quote1.price)
{
cout << "拷贝构造函数" << endl;
}
Quote& operator=(const Quote& quote2)//拷贝赋值运算符
{
if (*this != quote2)//防止自赋值的情况
{
bookNo = quote2.bookNo;
price = quote2.price;
}
cout << "拷贝赋值运算符" << endl;
return *this;
}
Quote(const Quote&& quote3) :bookNo(move(quote3.bookNo)), price(move(quote3.price))
{
cout << "移动构造函数" << endl;
}
Quote& operator=(const Quote&& quote4)
{
if (*this != quote4)
{
bookNo = move(quote4.bookNo);
price = move(quote4.price);
}
cout << "移动赋值运算符" << endl;
return *this;
}
string isbn() const { return bookNo; }
virtual double net_price(size_t n) const
{
return n * price;
}
virtual ~Quote() = default;
private:
string bookNo;
protected :
double price = 0.0;
};
bool operator !=(const Quote& rhs, const Quote& rhs1)
{
if (rhs.bookNo == rhs1.bookNo && rhs.price == rhs1.price)
{
return false;
}
else
return true;
}
double print_total(ostream &os, const Quote &item, size_t n)
{
double ret = item.net_price(n);
os << "ISBN: " << item.isbn()
<< " # sold: " << n << " total due: " << ret << endl;
return ret;
}
#endif // ! QUOTE_H
15.27:
class Bulk_quote : public Quote {
public:
Bulk_quote() = default;
Bulk_quote(const string& book, double price, size_t qty, double disc) :
Quote(book, price), qty(qty), discount(disc) {}
//继承拷贝构造函数
Bulk_quote(const Bulk_quote& rhs):Quote(rhs) {}
//继承拷贝赋值运算符
Bulk_quote& operator=(const Bulk_quote& rhs)
{
Quote::operator=(rhs);
return *this;
}
//继承移动构造函数
Bulk_quote(const Bulk_quote&& rhs) : Quote(move(rhs)) {}
//继承移动赋值运算符
Bulk_quote& operator=(const Bulk_quote&& rhs)
{
Quote::operator=(move(rhs));
return *this;
}
double net_price(size_t cnt) const override//允许派生类显示的注明它将使用哪个成员函数改写基类的虚函数
{
if (cnt >= qty)
{
return cnt*(1-discount)*price;
}
else
{
return cnt*price;
}
}
void debug()
{
cout<<"This is bulk_quote Class"<<endl;
cout<<"DISCOUNT: "<<discount<<endl;
cout<<"Min_qty: "<<qty<<endl;
cout<<"Price: "<<price<<endl;
}
private:
size_t qty;
double discount;
};
15.28:
#ifndef QUOTE_H
#define QUOTE_H
#include <iostream>
#include <string>
using namespace std;
class Quote {
friend double print_total(ostream &os, const Quote &item, size_t n);
//friend bool operator != (const Quote& rhs, const Quote& rhs1);
public:
Quote() = default;
Quote(const string &book,double sales_price):
bookNo(book),price(sales_price){}
Quote(const Quote& quote1) : bookNo(quote1.bookNo), price(quote1.price)
{
cout << "拷贝构造函数" << endl;
}
/*Quote& operator=(const Quote& quote2)//拷贝赋值运算符
{
if (*this != quote2)//防止自赋值的情况
{
bookNo = quote2.bookNo;
price = quote2.price;
}
cout << "拷贝赋值运算符" << endl;
return *this;
}*/
Quote(const Quote&& quote3) :bookNo(move(quote3.bookNo)), price(move(quote3.price))
{
cout << "移动构造函数" << endl;
}
/*Quote& operator=(const Quote&& quote4)
{
if (*this != quote4)
{
bookNo = move(quote4.bookNo);
price = move(quote4.price);
}
cout << "移动赋值运算符" << endl;
return *this;
}*/
string isbn() const { return bookNo; }
virtual double net_price(size_t n) const
{
cout << "Quote" << endl;
return n * price;
}
virtual ~Quote() = default;
private:
string bookNo;
protected :
double price = 0.0;
};
/*bool operator !=(const Quote& rhs, const Quote& rhs1)
{
if (rhs.bookNo == rhs1.bookNo && rhs.price == rhs1.price)
{
return false;
}
else
return true;
}*/
double print_total(ostream &os, const Quote &item, size_t n)
{
double ret = item.net_price(n);
os << "ISBN: " << item.isbn()
<< " # sold: " << n << " total due: " << ret << endl;
return ret;
}
class Bulk_quote : public Quote {
public:
Bulk_quote() = default;
Bulk_quote(const string& book, double price, size_t qty, double disc) :
Quote(book, price), qty(qty), discount(disc) {}
//继承拷贝构造函数
/* Bulk_quote(const Bulk_quote& rhs):Quote(rhs) {}
//继承拷贝赋值运算符
Bulk_quote& operator=(const Bulk_quote& rhs)
{
Quote::operator=(rhs);
return *this;
}
//继承移动构造函数
Bulk_quote(const Bulk_quote&& rhs) : Quote(move(rhs)) {}
//继承移动赋值运算符
Bulk_quote& operator=(const Bulk_quote&& rhs)
{
Quote::operator=(move(rhs));
return *this;
} */
double net_price(size_t cnt) const override//允许派生类显示的注明它将使用哪个成员函数改写基类的虚函数
{
cout << "Bulk_quote" << endl;
if (cnt >= qty)
{
return cnt*(1-discount)*price;
}
else
{
return cnt * price;
}
}
void debug()
{
cout<<"This is bulk_quote Class"<<endl;
cout<<"DISCOUNT: "<<discount<<endl;
cout<<"Min_qty: "<<qty<<endl;
cout<<"Price: "<<price<<endl;
}
private:
size_t qty;
double discount;
};
#endif // ! QUOTE_H
//test.cpp
#include <iostream>
#include <vector>
#include <memory>
#include "Quote.h"
using namespace std;
int main(int argc, char **argv)
{
vector<Quote> basket;
Bulk_quote b1(string("无声告白"), 35.0, 10, 0.25);
Bulk_quote b2(string("上海堡垒"), 38.0, 15, 0.3);
Bulk_quote b3(string("嫌疑人x的献身"), 35.0, 18, 0.35);
Bulk_quote b4(string("解忧杂货店"), 39.5, 16, 0.24);
basket.push_back(b1);
basket.push_back(b2);
basket.push_back(b3);
basket.push_back(b4);
double total = 0.0;
for (auto &c : basket)
{
total += c.net_price(20);
cout << total << endl;
}
cout << "total net_price: " << total << endl;
vector<shared_ptr<Quote>> basket1;
basket1.push_back(make_shared<Bulk_quote>(b1));
basket1.push_back(make_shared<Bulk_quote>(b2));
basket1.push_back(make_shared<Bulk_quote>(b3));
basket1.push_back(make_shared<Bulk_quote>(b4));
double total1 = 0.0;
for (auto &c : basket1)
{
total1 += c->net_price(20);
cout << total1 << endl;
}
cout << "total1 net_price: " << total1 << endl;
system("pause");
return 0;
}
15.29:
程序产生的结果会存在差异。因为当通过Quote类型的对象调用虚函数net_price时,不实行动态绑定,调用的是Quote类中定义的版本;而通过Quote类型的指针调用虚函数net_price,实行动态绑定,而该指针实际指向Bulk_quote类中定义的版本。
15.30:
//Basket.h
#ifndef BASKET_H
#define BASKET_H
#include <iostream>
#include <string>
#include <set>
#include <memory>
#include "Quote.h"
using namespace std;
class Basket {
//自定义compare函数
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 };
public:
void add_item(const shared_ptr<Quote> &sale)
{
items.insert(sale);
}
void add_item(const Quote &sale)
{
items.insert(shared_ptr<Quote>(sale.clone()));
}
void add_item(Quote &&sale)
{
items.insert(shared_ptr<Quote>(sale.clone()));
}
double total_receipt(ostream &os) const;
};
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));
}
os << "Total Sale: "<< sum << endl;
return sum;
}
#endif // !BASKET_H
//Quote.h添加
virtual Quote* clone() const & { return new Quote(*this); }
virtual Quote* clone() && {return new Quote(move(*this)); }
virtual Bulk_quote* clone() const & { return new Bulk_quote(*this); }
virtual Bulk_quote* clone() && {return new Bulk_quote(move(*this)); }
//test.cpp
#include <iostream>
#include <vector>
#include <memory>
#include "Basket.h"
#include "Quote.h"
using namespace std;
int main(int argc, char **argv)
{
Bulk_quote b1(string("无声告白"), 35.0, 10, 0.25);
Bulk_quote b2(string("上海堡垒"), 38.0, 15, 0.3);
Bulk_quote b3(string("嫌疑人x的献身"), 35.0, 18, 0.35);
Bulk_quote b4(string("解忧杂货店"), 39.5, 16, 0.24);
Basket bsk;
bsk.add_item(make_shared<Bulk_quote>(b1));
bsk.add_item(make_shared<Bulk_quote>(b2));
bsk.add_item(make_shared<Bulk_quote>(b3));
bsk.add_item(make_shared<Bulk_quote>(b4));
cout << "total_receipt: " << bsk.total_receipt(cout) << endl;
system("pause");
return 0;
}
15.31:
(a)共创建12个对象:6个Query_base对象以及其相关联的句柄。6个Query_base对象分别是3个WordQuery对象,1个NotQuery对象,1个AndQuery对象,1个OrQuery对象。
(b)与(a)相同。
(c)共创建14个对象:7个Query_base对象以及其相关联的句柄。7个Query_base对象分别是4个WordQuery对象,2个AndQuery对象,1个OrQuery对象。
15.32:
Query类并未定义自己的拷贝/移动控制成员,当进行这些操作时,执行默认的语义;其唯一的数据成员是Query_base的shared_ptr,因此当执行这些操作时,调用shared_ptr的对应控制成员,从而实现多个Query对象共享一个Query_base。而shared_ptr的控制成员调用Query_base的控制成员时,由于指向的可能是Query_base的派生类对象,因此可能在类层次中进行相应的拷贝移动操作,调用Query_base的派生类的相应控制成员
15.33:
Query_base是一个抽象类,不能直接声明其对象
当其派生类对象进行这些操作时,会调用Query_base相应的控制成员,但Query_base并未定义自己的拷贝移动控制成员,所以执行这些操作时,会执行默认语义,什么都不会发生
15.34:
(a)执行的所有构造函数
WordQuery(const string&)
Query(const string&)
WordQuery(const string&)
Query(const string&)
WordQuery(const string&)
Query(const string&)
BinaryQuery(const Query&, const Query&, string s)
AndQuery(const Query&,const Query&)
Query(shared_ptr<Query_base>)
BinaryQuery(const Query&, const Query&, string s)
OrQuery(const Query&,const Query&)
Query(shared_ptr<Query_base>)
(b)调用的rep
Query_rep、BinaryQuery_rep、Query_rep、WordQuery_rep、Query_rep、BinaryQuery_rep、Query_rep
WordQuery_rep、、Query_rep、WordQuery_rep
(c)调用的eval
Query类的eval,OrQuery类的eval,AndQuery类的eval,WordQuery类的eval
15.35、15.36:
#ifndef QUERY_H
#define QUERY_H
#include <iostream>
#include <string>
#include <vector>
#include <set>
#include <map>
using namespace std;
class TextQuery;
//QueryResult保存查询的结果
class QueryResult
{
public:
typedef vector<string>::size_type line_no;//保存出现的行号,使用类型别名
friend ostream& operator<<(ostream&, const QueryResult&);//输出查询结果
public:
QueryResult(const string& s, shared_ptr<std::set<line_no>> set,
shared_ptr<vector<string>> v) : word(s), nos(set), input(v) { }
private:
string word;//查询的单词
shared_ptr<std::set<line_no>> nos;//用set保存出现的行号,自动排序
shared_ptr<vector<string>> input;//输入文件vector的指针
};
//TextQuery接受输入文件,并保存,生成map
class TextQuery
{
public:
typedef vector<string>::size_type line_no;
TextQuery(ifstream&);//接受输入文件的构造函数
QueryResult query(const string&) const;//具体的查询函数
private:
shared_ptr<vector<string>> input;//保存输入的vector的智能指针
map<string, shared_ptr<set<line_no>>> result;//map保存单词出现的行和列
};
//抽象基类
class Query_base {
friend class Query;
protected:
using line_no = TextQuery::line_no;
virtual ~Query_base() = default;
private:
//eval返回与当前Query匹配的QueryResult
virtual QueryResult eval(const TextQuery&) const = 0;
//rep是表示查询的一个string
virtual string rep() const = 0;
};
//管理Query_base继承体系的接口类
class Query {
//运算符需要访问接受shared_ptr的构造函数,而该构造函数是私有的,所以定义为Query类的友元
friend Query operator~(const Query&);
friend Query operator|(const Query&, const Query&);
friend Query operator&(const Query&, const Query&);
public:
Query(const string&); //构建一个新的WordQuery,查询单词
//接口函数,调用对应的Query_base操作
QueryResult eval(const TextQuery &t) const
{
return q->eval(t);
}
string rep() const {
cout << "Query_rep" << endl;
return q->rep(); }
private:
Query(shared_ptr<Query_base> query) :q(query) { cout << "Query(shared_ptr<Query_base>)" << endl; } //构造函数,接受一个Query_base的指针
shared_ptr<Query_base> q; //保存一个指向基类的指针
};
//Query的输出运算符
ostream & operator<<(ostream &os, const Query &query)
{
return os << query.rep();
}
//派生类
class WordQuery : public Query_base { //查询单词
friend class Query;
WordQuery(const string &s) : query_word(s) { cout << "WordQuery(const string &)" << endl; }
QueryResult eval(const TextQuery &t) const
{
return t.query(query_word);
}
string rep() const
{
cout << "WordQuery_rep" << endl;
return query_word;
}
string query_word; //要查找的单词
};
inline Query::Query(const string &s) : q(new WordQuery(s)) { cout << "Query(const string &)" << endl; }
class NotQuery : public Query_base {
friend Query operator~(const Query &);
NotQuery(const Query &q) : query(q) { cout << "NotQuery(const Query &)" << endl; }
string rep() const {
cout << "NotQuery_rep" << endl;
return "~(" + query.rep() + ")"; }
QueryResult eval(const TextQuery&) const;
Query query;
};
/*QueryResult NotQuery::eval(const TextQuery& text) const
{
}*/
inline Query operator~(const Query &operand)
{
return shared_ptr<Query_base>(new NotQuery(operand));
}
class BinaryQuery :public Query_base {
protected:
BinaryQuery(const Query &l, const Query &r, string s) :
lhs(l), rhs(r), opSym(s) {
cout << "BinaryQuery(const Query&, const Query&, string s)" << endl;
}
//抽象类,BinaryQuery不定义eval,而是继承了该纯虚函数
string rep() const {
cout << "BinaryQuery_rep" << endl;
return "(" + lhs.rep() + " "
+ opSym + ""
+ rhs.rep() + ")";
}
Query lhs, rhs; //左侧和右侧运算对象
string opSym; //操作符的名字
};
class AndQuery : public BinaryQuery {
friend Query operator&(const Query&, const Query&);
AndQuery(const Query &left, const Query &right) :
BinaryQuery(left, right, "&") {
cout << "AndQuery(const Query&, const Query&)" << endl;
}
QueryResult eval(const TextQuery&) const;
};
/*QueryResult AndQuery::eval(const TextQuery &text) const
{
}*/
inline Query operator&(const Query &lhs, const Query &rhs)
{
return shared_ptr<Query_base>(new AndQuery(lhs, rhs));
}
class OrQuery : public BinaryQuery {
friend Query operator|(const Query&, const Query&);
OrQuery(const Query &left, const Query &right) :
BinaryQuery(left, right, "|") {
cout << "OrQuery(const Query&, const Query&)" << endl;
}
QueryResult eval(const TextQuery&) const;
};
/*QueryResult OrQuery::eval(const TextQuery &text) const
{
}*/
inline Query operator|(const Query &lhs, const Query &rhs)
{
return shared_ptr<Query_base>(new OrQuery(lhs, rhs));
}
#endif // ! QUERY_H
#include <iostream>
#include "Query.h"
using namespace std;
int main()
{
Query q = Query("fiery") & Query("bird") | Query("wind");
cout << q;
system("pause");
return 0;
}
15.37:
书中的实现方式是用Query类封装了Query_base指针,管理实际查询处理用到的不同Query类型对象。如果不使用Query类,则涉及使用Query类型的地方,都要改成Query_base指针。如创建单个词查询时,就必须创建WordQuery类而不是Query对象。几个重载的布尔运算符也不能再针对Query对象,而需针对Query_base指针,从而复杂的查询请求无法写成目前的简单形式,而需逐个运算完成,将结果赋予Query_base指针,然后再进行下一步运算。资源管理方面也需要重新设计。因此,当前的设计仍是最佳方式。
15.38:
(1)不合法,因为BinaryQuery是抽象类
(2)不合法,不能将Query转换成AndQuery
(3)不合法,不能将Query转换成OrQuery
15.40:
OrQuery的eval函数从lhs与rhs获取范围构造set,而set的构造和插入操作都可以正确处理空范围,因此,无论lhs与rhs所结果是否为空,都能得到正确结果
15.41:
#ifndef QUERY1_H
#define QUERY1_H
#include <iostream>
#include <string>
#include "Query.h"
using namespace std;
class Query {
public:
Query(const string &s);
Query(Query &query) : q(query.q), cnt(query.cnt) { ++*cnt; }
Query& operator=(const Query& query);
~Query();
private:
Query(Query_base *query) :q(query), cnt(new int(1)) {}
Query_base * q;
int* cnt;
};
inline Query::Query(const string &s) :q(new WordQuery(s)), cnt(new int(1)) {}
inline Query& Query::operator=(const Query& query)
{
++*query.cnt;
if (--*query.cnt == 0)
{
delete q;
delete cnt;
}
q = query.q;
cnt = query.cnt;
return *this;
}
inline Query::~Query()
{
if (--*cnt == 0)
{
delete q;
delete cnt;
}
}
inline Query operator&(const Query &lhs, const Query &rhs)
{
return new AndQuery(lhs, rhs);
}
inline Query operator|(const Query &lhs, const Query &rhs)
{
return new OrQuery(lhs, rhs);
}
inline Query operator~(const Query &operand)
{
return new NotQuery(operand);
}
#endif // !QUERY1_H