我对编程很新,所以如果答案显而易见,请坚持我的问题。
在Lippman,Lajoie和Moo的C ++ Primer第5版第15.9节中,该部分涉及编程继承层次结构。它基本上是一个抽象类Query_base
,其子项为WordQuery
,NotQuery
和BinaryQuery
,其中最后一个分为AndQuery
和{{1} }}。 OrQuery
层次结构通过名为Query_base
的接口类通过指针访问。此设置背后的基本思想是使用复合查询,例如:
Query
(这些运算符生成指向Query q = Query("fiery") & Query("bird") | Query("wind")
- 类型对象的Query
个对象,例如,“Query_base
”生成&
,“AndQuery
'生成~
。
然后可以搜索文本文档以查找符合查询规则的行。)
类Query_base如下:
NotQuery
所有Query_base子实现eval()和rep(),因此可以实例化。
类Query的设计如下:
class Query_base {
friend class Query;
protected:
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;
课程有什么问题吗?我们可以让Query
类作为层次结构和接口的基础,并摆脱Query_base
类吗?我认识到,Query
代表它不能,因为它具有纯虚函数,但这些可以改变。例如,我是否只能将Query_base
和Query
的{{1}}函数实现转移到eval()
?这样做有什么不对吗? rep()
中的Query_base
是否会使事情复杂化并且是分离的基础,如果是,我们可以解决这个问题吗?提前致谢!
答案 0 :(得分:0)
如果我们继续实现所有这些运算符和其他子查询类型,则需要分离。让我们想象一下,例如&amp;运算符可能看起来像。
&
运算符应构造一个查询,而该查询应包含另外两个查询。
因此,AndQuery
类可以这样定义:
class AndQuery: public BinaryQuery {
public:
AndQuery(const Query_base& lhs, const Query_base& rhs);
AndQuery(Query_base&& lhs, Query_base&& rhs);
...
QueryResult eval(const TextQuery& t) override;
private:
// required members and private methods...
// two principal members, lhsQuery and rhsQuery for
// left hand side subquery and light hand side subquery
// correspondingly are defined in `BinaryQuery`
};
并且,在一个简单的未经优化的案例中,AndQuery
应以某种方式执行搜索(eval()
):
QueryResult AndQuery::eval(const TextQuery& t) {
QueryResult lhsResult = lhsQuery.eval(t);
QueryResult rhsResult = rhsQeury.eval(t);
// the resulting ResultSet should include only entries
// from both result sets
for(auto it = lhsResult.begin(); it != lhsResult.end(); ++it)
if (rhsResult.find(*it) == rhsResult::cend())
it = lhsResult.erase(it);
// now we can return lhsResult because we have erased all elements from it
// which weren't in rhsResult
return lhsResult;
}
其他查询组件子类有自己的特定实现。反过来,Query
有自己的一组特定方法,比如从字符串构造查询。如果没有纯虚拟Query_base
,我们必须与所有组件子类共享Query
的实现细节。此外,我们还必须让这些课程对外部用户可见。
使用单独的&#34;界面&#34; Query
课程我们为子系统的用户提供了清晰易懂的精简接口。
答案 1 :(得分:0)
除了上面的评论,我认为这个设计还与c++中的多态性有关,它只通过引用和指针支持,而不是对象本身。
通过使用一个没有层次结构的“Query”对象和一个具有层次结构和多态性的嵌入到Query_Base的智能指针,类的用户可以使用Query对象来实现多态性的效果。