F
fl
Hi,
I am learning C++ with "C++ Primer" 4th edition. There is a class derivation example in Chapter 15. When I step through the code, I find that the base class destructor
,,,,,,,
~Query() { decr_use(); }
,,,,,,,
executes after the derived class AndQuery() (which is derived from BinaryQuery, which is then derived from Query_base) constructor runs:
,,,,,,,,,,,,,,,,,,
AndQuery(Query left, Query right): BinaryQuery(left, right, "&") { }
,,,,,,,,,,,,,,,,,,
The above problem appears when I run
Query orq = Query(sought1) & Query(sought2);
It triggers the "and" operator. I see that it copies "left" to "lhs" etc.:
BinaryQuery(Query left, Query right, std::string op): lhs(left), rhs right, oper(op) { }
The next call
~Query() { decr_use(); }
puzzles me a lot.
Could you explain it to me?
Thanks in advance
................
// private, abstract class acts as a base class for concrete query types
class Query_base {
friend class Query;
protected:
typedef TextQuery::line_no line_no;
virtual ~Query_base() { }
private:
// eval returns the |set| of lines that this Query matches
virtual std::set<line_no>
eval(const TextQuery&) const = 0;
// display prints the query
virtual std:stream&
display(std:stream& = std::cout) const = 0;
};
// handle class to manage the Query_base inheritance hierarchy
class Query {
// these operators need access to the Query_base* constructor
friend Query operator~(const Query &);
friend Query operator|(const Query&, const Query&);
friend Query operator&(const Query&, const Query&);
public:
Query(const std::string&); // builds a new WordQuery
// copy control to manage pointers and use counting
Query(const Query &c): q(c.q), use(c.use) { ++*use; }
~Query() { decr_use(); }
Query& operator=(const Query&);
// interface functions: will call corresponding Query_base operations
std::set<TextQuery::line_no>
eval(const TextQuery &t) const { return q->eval(t); }
std:stream &display(std:stream &os) const
{ return q->display(os); }
private:
Query(Query_base *query): q(query),
use(new std::size_t(1)) { }
Query_base *q;
std::size_t *use;
void decr_use()
{ if (--*use == 0) { delete q; delete use; } }
};
inline Query& Query:perator=(const Query &rhs)
{
++*rhs.use;
decr_use();
q = rhs.q;
use = rhs.use;
return *this;
}
inline std:stream&
operator<<(std:stream &os, const Query &q)
{
return q.display(os);
}
class WordQuery: public Query_base {
friend class Query; // Query uses the WordQuery constructor
WordQuery(const std::string &s): query_word(s) { }
// concrete class: WordQuery defines all inherited pure virtual functions
std::set<line_no> eval(const TextQuery &t) const
{ return t.run_query(query_word); }
std:stream& display (std:stream &os) const
{ return os << query_word; }
std::string query_word; // word for which to search
};
inline
Query::Query(const std::string &s): q(new WordQuery(s)),
use(new std::size_t(1)) { }
class NotQuery: public Query_base {
friend Query operator~(const Query &);
NotQuery(Query q): query(q) { }
// concrete class: NotQuery defines all inherited pure virtual functions
std::set<line_no> eval(const TextQuery&) const;
std:stream& display(std:stream &os) const
{ return os << "~(" << query << ")"; }
const Query query;
};
class BinaryQuery: public Query_base {
protected:
BinaryQuery(Query left, Query right, std::string op):
lhs(left),
rhs(right),
oper(op)
{ }
// abstract class: BinaryQuery doesn't define eval
std:stream& display(std:stream &os) const
{ return os << "(" << lhs << " " << oper << " "
<< rhs << ")"; }
const Query lhs, rhs; // right- and left-hand operands
const std::string oper; // name of the operator
};
class AndQuery: public BinaryQuery {
friend Query operator&(const Query&, const Query&);
AndQuery(Query left, Query right):
BinaryQuery(left, right, "&") { }
// concrete class: AndQuery inherits display and defines remaining pure virtual
std::set<line_no> eval(const TextQuery&) const;
};
class OrQuery: public BinaryQuery {
friend Query operator|(const Query&, const Query&);
OrQuery(Query left, Query right):
BinaryQuery(left, right, "|") { }
// concrete class: OrQuery inherits display and defines remaining pure virtual
std::set<line_no> eval(const TextQuery&) const;
};
inline Query operator&(const Query &lhs, const Query &rhs)
{
return new AndQuery(lhs, rhs);
}
I am learning C++ with "C++ Primer" 4th edition. There is a class derivation example in Chapter 15. When I step through the code, I find that the base class destructor
,,,,,,,
~Query() { decr_use(); }
,,,,,,,
executes after the derived class AndQuery() (which is derived from BinaryQuery, which is then derived from Query_base) constructor runs:
,,,,,,,,,,,,,,,,,,
AndQuery(Query left, Query right): BinaryQuery(left, right, "&") { }
,,,,,,,,,,,,,,,,,,
The above problem appears when I run
Query orq = Query(sought1) & Query(sought2);
It triggers the "and" operator. I see that it copies "left" to "lhs" etc.:
BinaryQuery(Query left, Query right, std::string op): lhs(left), rhs right, oper(op) { }
The next call
~Query() { decr_use(); }
puzzles me a lot.
Could you explain it to me?
Thanks in advance
................
// private, abstract class acts as a base class for concrete query types
class Query_base {
friend class Query;
protected:
typedef TextQuery::line_no line_no;
virtual ~Query_base() { }
private:
// eval returns the |set| of lines that this Query matches
virtual std::set<line_no>
eval(const TextQuery&) const = 0;
// display prints the query
virtual std:stream&
display(std:stream& = std::cout) const = 0;
};
// handle class to manage the Query_base inheritance hierarchy
class Query {
// these operators need access to the Query_base* constructor
friend Query operator~(const Query &);
friend Query operator|(const Query&, const Query&);
friend Query operator&(const Query&, const Query&);
public:
Query(const std::string&); // builds a new WordQuery
// copy control to manage pointers and use counting
Query(const Query &c): q(c.q), use(c.use) { ++*use; }
~Query() { decr_use(); }
Query& operator=(const Query&);
// interface functions: will call corresponding Query_base operations
std::set<TextQuery::line_no>
eval(const TextQuery &t) const { return q->eval(t); }
std:stream &display(std:stream &os) const
{ return q->display(os); }
private:
Query(Query_base *query): q(query),
use(new std::size_t(1)) { }
Query_base *q;
std::size_t *use;
void decr_use()
{ if (--*use == 0) { delete q; delete use; } }
};
inline Query& Query:perator=(const Query &rhs)
{
++*rhs.use;
decr_use();
q = rhs.q;
use = rhs.use;
return *this;
}
inline std:stream&
operator<<(std:stream &os, const Query &q)
{
return q.display(os);
}
class WordQuery: public Query_base {
friend class Query; // Query uses the WordQuery constructor
WordQuery(const std::string &s): query_word(s) { }
// concrete class: WordQuery defines all inherited pure virtual functions
std::set<line_no> eval(const TextQuery &t) const
{ return t.run_query(query_word); }
std:stream& display (std:stream &os) const
{ return os << query_word; }
std::string query_word; // word for which to search
};
inline
Query::Query(const std::string &s): q(new WordQuery(s)),
use(new std::size_t(1)) { }
class NotQuery: public Query_base {
friend Query operator~(const Query &);
NotQuery(Query q): query(q) { }
// concrete class: NotQuery defines all inherited pure virtual functions
std::set<line_no> eval(const TextQuery&) const;
std:stream& display(std:stream &os) const
{ return os << "~(" << query << ")"; }
const Query query;
};
class BinaryQuery: public Query_base {
protected:
BinaryQuery(Query left, Query right, std::string op):
lhs(left),
rhs(right),
oper(op)
{ }
// abstract class: BinaryQuery doesn't define eval
std:stream& display(std:stream &os) const
{ return os << "(" << lhs << " " << oper << " "
<< rhs << ")"; }
const Query lhs, rhs; // right- and left-hand operands
const std::string oper; // name of the operator
};
class AndQuery: public BinaryQuery {
friend Query operator&(const Query&, const Query&);
AndQuery(Query left, Query right):
BinaryQuery(left, right, "&") { }
// concrete class: AndQuery inherits display and defines remaining pure virtual
std::set<line_no> eval(const TextQuery&) const;
};
class OrQuery: public BinaryQuery {
friend Query operator|(const Query&, const Query&);
OrQuery(Query left, Query right):
BinaryQuery(left, right, "|") { }
// concrete class: OrQuery inherits display and defines remaining pure virtual
std::set<line_no> eval(const TextQuery&) const;
};
inline Query operator&(const Query &lhs, const Query &rhs)
{
return new AndQuery(lhs, rhs);
}