天天看點

C++Primer第五版 第十五章習題答案(31~40)

後面的題目主要是進行練習,即使是照搬書本上的例子,也要做一做

31:知識點1:繼承體系:is  a ,和has  a 的差別。

知識點2:将層次關系隐藏與接口類之中,儲存一個基類(抽象基類)派生類的對象的指針

C++Primer第五版 第十五章習題答案(31~40)

32:

拷貝:調用合成的拷貝構造函數,将智能指針q的内容複制到新對象的對應成員,使智能指針q計數+1

移動:調用合成的移動構造函數,将智能指針q的内容移動到新對象的對應成員,使智能指針q指向NULL

指派:調用合成的拷貝指派運算符,将智能指針q的内容替換為參數對象的對應成員的内容,使q計數-1,并讓參數計數+1

摧毀:調用合成的析構函數,清理自身,并調用q的析構函數,使計數-1

33:

由于沒有資料成員,是以合成的拷貝控制足以應付所有問題

34:

(a): 

1: Query::Query(const std::string& s) 

2: WordQuery::WordQuery(const std::string& s) 

3: AndQuery::AndQuery(const Query& left, const Query& right);

4: BinaryQuery(const Query&l, const Query& r, std::string s);

5: Query::Query(std::shared_ptr<Query_base> query) 2times

6: OrQuery::OrQuery(const Query& left, const Query& right);

7: BinaryQuery(const Query&l, const Query& r, std::string s);

8: Query::Query(std::shared_ptr<Query_base> query) 2times

(b):運算符"<<"會調用Query的rep成員,Query.rep()調用的是OrQuery的rep(因為初始化對象q時使用的是值是"|"運算符傳回的Query,而該對象的智能指針q指向的是一個OrQuery對象),而OrQuery并沒有定義rep成員,是以直接使用直接基類BinaryQuery的rep成員

(c):q調用的是OrQuery的eval函數,因為是虛函數,且使用引用調用,需動态綁定

35:書上有現成的代碼,敲上就行

#ifndef QUERY_H
#define QUERY_H

#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:
	/*using line_no = vector<string>::size_type;//C++11新标準,可以使用typedef代替*/
	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儲存單詞出現的行和列
};

//抽象基類Query_base,用于派生
class Query_base
{
	friend class Query;
private:
	//純虛函數,傳回與目前Query比對的QueryResult
	/*virtual QueryResult eval(const TextQuery&) const = 0;*/
	//純虛函數,儲存用于查詢的string
	virtual string rep() const = 0;
protected:
	/*using line_no = vector<string>::size_type;//C++11新标準,可以使用typedef代替*/
	typedef vector<string>::size_type line_no;
	virtual ~Query_base() /*= default*/;//C++11新标準,不加
};

//查詢基類 Query
class Query
{
	//定義運算符函數
	friend Query operator~(const Query&);
	friend Query operator|(const Query&,const Query&);
	friend Query operator&(const Query&,const Query&);
public:
	Query(const string&s);//新的構造函數,查詢單詞
	//接口函數
// 	QueryResult eval(const TextQuery &t) const
// 	{
// 		return q->eval(t);//查詢結果
// 	}//事先無需定義
	string rep() const
	{
		return q->rep();//查詢單詞
	}
private:
	Query(shared_ptr<Query_base> query):q(query){}//構造函數,接受一個Query_base的指針
	shared_ptr<Query_base> q;//儲存一個指向基類的指針,私有成員
};

std::ostream &operator<<(std::ostream &os, const Query query)  
{  
	return os << query.rep();  
} 

//基礎查詢單詞類
class WordQuery:public Query_base
{
	//所有成員皆為private,
	friend class Query;//Query需要使用其構造函數
	WordQuery(const string &s):Query_word(s){cout<<"WordQuery"<<endl;}//初始化

	QueryResult eval(const TextQuery& t) const
	{
		return t.query(Query_word);
	}//純虛函數,必須重寫
	string rep() const
	{
		return Query_word;
	}//純虛函數,必須重寫
	string Query_word;
};
inline Query::Query(const string &s):q(new WordQuery(s)){cout<<"Query"<<endl;}//程式順序執行,所用之對象必須進行聲明

//NotQuery類,取反的query
class NotQuery:public Query_base
{
	friend Query operator~(const Query&);
	NotQuery(const Query&q):query(q){cout<<"NotQuery"<<endl;}//構造函數

	string rep()
	{
		return "~("+query.rep()+")";//表示不需要查詢的單詞
	}
	QueryResult eval(const TextQuery&);
	Query query;
};
// inline Query operator~(const Query&operand)
// {
// 	return shared_ptr<Query_base>(new NotQuery(operand));
// }

//BinaryQuery類,一個抽象基類,因為繼承了基類的純虛函數eval()
class BinaryQuery:public Query_base
{
protected:
	BinaryQuery(const Query&l, const Query&r,string s):lhs(l),rhs(r),opSym(s){cout<<"BinaryQuery"<<endl;}//構造函數
	string rep() const
	{	cout<<"Binary_rep"<<endl;//36題
		return "("+lhs.rep()+" "+opSym+" "+rhs.rep()+")";
	}
	Query lhs,rhs;
	string opSym;//運算符的名字
};

//AndQuery類,繼承自抽象基類BinaryQuery
class AndQuery:public BinaryQuery
{
protected:
	friend Query operator&(const Query&,const Query&);//之前定義的運算符
	AndQuery(const Query&left, const Query&right):BinaryQuery(left,right,"&"){cout<<"AndQuery"<<endl;}//構造函數
	//傳回查詢結果的函數
	QueryResult eval(const TextQuery&);
};
// inline Query operator&(const Query&lhs, const Query&rhs)
// {
// 	return shared_ptr<Query_base>(new AndQuery(lhs,rhs));//在未定義純虛函數eval()時,為抽象基類,不可執行個體化
// }

//OrQuery類,繼承自抽象基類BinaryQuery
class OrQuery:public BinaryQuery
{
protected:
	friend Query operator|(const Query&,const Query&);//之前定義的運算符
	OrQuery(const Query&left, const Query&right):BinaryQuery(left,right,"|"){cout<<"OrQuery"<<endl;}//構造函數
	//傳回查詢結果的函數
	QueryResult eval(const TextQuery&);
};
// inline Query operator|(const Query&lhs, const Query&rhs)
// {
// 	return shared_ptr<Query_base>(new OrQuery(lhs,rhs));
// }

#endif QUERY_H
           

36:見上代碼,加一條語句即可

37:

若要含有base類型的成員,應當在派生類中聲明 friend class Query_base

38:

(a):錯誤,Binary_Query是抽象基類,不能執行個體化

(B):錯誤,不存在AndQuery到Query之間的轉化

(c):同上

39:加上書中的eval函數即可

40:

如果rhs是空集,那麼内容到lhs

如果lhs是空集,那麼内容為rhs

如果都為空集,那麼内容為空

繼續閱讀