c++ primer第五版----学习笔记(十五)Ⅱ

部分习题解答:

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

猜你喜欢

转载自blog.csdn.net/qq_38790716/article/details/82944884