多层继承(inheritance) 的 使用 及 示例
本文地址: http://blog.csdn.net/caroline_wendy/article/details/16856547
动态绑定只能应用在虚函数(virtual function), 通过指针(->)或引用(.)调用; 声明基类指针, 绑定派生类对象;
可以使用"shared_ptr<Abstract_Base_Class> p(new Derived_Class(para));"的形式, 动态绑定派生的类;
可以为动态基类添加一个接口(interface), 使用友元函数, 访问基类的私有成员变量; 并把具体操作写入接口中;
如果一个派生类, 没有实现抽象基类的纯虚函数, 则会继承此函数, 那么这个派生类也是抽象基类;
抽象基类不能创建具体的对象, 但是可以实现具体的方法, 为派生类提供继承;
面向对象编程: 抽象(abstraction), 即数据抽象(data abstraction);继承(inheritance);多态(polynorphism), 即动态绑定(dynamic binding).
具体代码如下, 详见注释:
/*
* cppprimer.cpp
*
* Created on: 2013.11.7
* Author: Caroline
*/
/*eclipse cdt, gcc 4.8.1*/
#include <iostream>
#include <fstream>
#include <sstream>
#include <string>
#include <vector>
#include <memory>
#include <algorithm>
#include <iterator>
#include <set>
#include <map>
using namespace std;
class QueryResult;
std::ostream& print(std::ostream& os, const QueryResult &qr);
class TextQuery {
public:
using line_no = std::vector<std::string>::size_type;
TextQuery(std::ifstream& );
QueryResult query(const std::string& ) const;
private:
std::shared_ptr<std::vector<std::string> > file; //文件内容
std::map<std::string, std::shared_ptr<std::set<line_no> > > wm; //词和行号的集合
};
/*把每一行放入text, 存入file(vector), 组成word和行号(set)的映射*/
TextQuery::TextQuery(std::ifstream &is) : file(new std::vector<std::string>)
{
std::string text;
while (std::getline(is, text)) {
file->push_back(text);
int n = file->size() - 1;
std::istringstream line(text);
std::string word;
while (line >> word) {
auto& lines = wm[word];
if (!lines)
lines.reset(new set<line_no>);
lines->insert(n);
}
}
}
class QueryResult {
friend std::ostream& print (std::ostream&, const QueryResult& );
public:
using line_no = std::vector<std::string>::size_type;
QueryResult (std::string s, //查询单词
std::shared_ptr<std::set<line_no>> p, //匹配行号
std::shared_ptr<std::vector<std::string>> f) : //输入文件
sought(s), lines(p), file(f) {}
std::set<line_no>::iterator begin() { return lines->begin(); }
std::set<line_no>::iterator end() { return lines->end(); }
std::shared_ptr<std::vector<std::string>> get_file() { return file; }
private:
std::string sought; //查找字符串
std::shared_ptr<std::set<line_no>> lines; //行号集合
std::shared_ptr<std::vector<std::string>> file; //文件集合
};
/*找到指定sought的集合, 返回迭代器, 传入string和set*/
QueryResult TextQuery::query(const std::string& sought) const {
static std::shared_ptr<std::set<line_no>> nodata(new std::set<line_no>);
auto loc = wm.find(sought);
if (loc == wm.end())
return QueryResult(sought, nodata, file); //没有找到, 不打印
else
return QueryResult(sought, loc->second, file); //按行号打印
};
std::string make_plural (std::size_t ctr, const std::string& word,
const std::string ending)
{
return (ctr > 1) ? word + ending : word;
}
std::ostream& print(std::ostream& os, const QueryResult &qr){
os << qr.sought << " occurs " << qr.lines->size() << " "
<< make_plural(qr.lines->size(), "time", "s") << std::endl;
for(auto num : *qr.lines)
os << "\t(line " << num+1 << ") " << *(qr.file->begin()+num) << std::endl;
return os;
}
void runQueries (std::ifstream &infile) {
TextQuery tq(infile);
while (true) {
std::cout << "enter word to look for, or q to quit: ";
std::string s;
if ( !(cin>>s) || s == "q" ) break;
print(std::cout, tq.query(s)) << std::endl;
}
}
/*抽象基类, 没有public成员*/
class Query_base {
friend class Query;
protected:
using line_no = TextQuery::line_no;
virtual ~Query_base() = default; //虚的析构函数
private:
virtual QueryResult eval (const TextQuery&) const = 0; //纯虚函数
virtual std::string rep() const = 0;
};
//为Query_base提供接口(interface)
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(); } //生成string版本的查询
private:
Query(std::shared_ptr<Query_base> query) : q(query) {}
std::shared_ptr<Query_base> q; //使用动态绑定
};
//重载输出(<<)操作符
std::ostream & operator<<(std::ostream &os, const Query &query)
{
return os << query.rep();
}
//单词查询类
class WordQuery : public Query_base {
friend class Query;
WordQuery (const std::string &s) : query_word (s) {}
QueryResult eval (const TextQuery &t) const { return t.query(query_word); }
std::string rep() const { return query_word; };
std::string query_word;
};
//Query接口实现动态绑定WordQuery
inline Query::Query (const std::string &s) : q(new WordQuery(s)) {}
//取反查询
class NotQuery : public Query_base {
friend Query operator~ (const Query &); //友元是取反函数
NotQuery (const Query &q) : query(q) {}
std::string rep() const {return "~("+query.rep()+")";}
QueryResult eval (const TextQuery &t) const;
Query query;
};
//实现取反操作, 动态绑定NotQuery对象
//最终使用的是WordQuery类, Query构建需要WordQuery, 再传入NotQuery;
inline Query operator~ (const Query &operand) {
return std::shared_ptr<Query_base> (new NotQuery(operand));
}
//二元查询, 没有eval, 则继承纯虚函数
class BinaryQuery : public Query_base {
protected:
BinaryQuery (const Query &l, const Query &r, std::string s) :
lhs(l), rhs(r), opSym(s) {}
std::string rep() const {
return "(" + lhs.rep() + " " + opSym + " " + rhs.rep() + ")"; }
Query lhs, rhs;
std::string opSym;
};
//取并查询
class AndQuery : public BinaryQuery {
friend Query operator& (const Query&, const Query&);
AndQuery (const Query& left, const Query& right) : BinaryQuery (left, right, "&") {}
QueryResult eval (const TextQuery&) const;
};
inline Query operator& (const Query& lhs, const Query& rhs) {
return std::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, "|") {}
QueryResult eval (const TextQuery&) const;
};
inline Query operator| (const Query& lhs, const Query& rhs) {
return std::shared_ptr<Query_base>(new OrQuery(lhs, rhs));
}
QueryResult OrQuery::eval(const TextQuery& text) const {
auto right = rhs.eval(text), left = lhs.eval(text);
auto ret_lines = std::make_shared<std::set<line_no> >(left.begin(), left.end());
ret_lines->insert(right.begin(), right.end());
return QueryResult(rep(), ret_lines, left.get_file());
}
QueryResult AndQuery::eval(const TextQuery& text) const {
auto left = lhs.eval(text), right = rhs.eval(text); //调用的是WordQuery的eval
auto ret_lines = std::make_shared<std::set<line_no>>();
std::set_intersection(left.begin(), left.end(), right.begin(), right.end(),
std::inserter(*ret_lines, ret_lines->begin()));
return QueryResult(rep(), ret_lines, left.get_file());
}
QueryResult NotQuery::eval(const TextQuery& text) const
{
auto result = query.eval(text); //调用WordQuery.eval;
auto ret_lines = std::make_shared<std::set<line_no>>();
auto beg = result.begin(), end = result.end();
auto sz = result.get_file()->size();
for (size_t n=0; n!=sz; ++n) {
if (beg==end || *beg != n )
ret_lines->insert(n);
else if (beg!=end)
++beg;
}
return QueryResult(rep(), ret_lines, result.get_file());
}
bool get_word(std::string& str) {
std::cout << "enter word to look for, or q to quit: " << std::endl;
if ( !(std::cin >> str) || str == "q" ){
std::cout << str;
return false;
}
else{
std::cout << str;
return true;
}
}
int main (void) {
std::ifstream infile;
infile.open("storyDataFile.txt");
TextQuery file = infile;
//Query q = ~Query("Alice");
//Query q = Query("hair") | Query("Alice");
//Query q = Query("hair") & Query("Alice");
Query q = Query("fiery") & Query("bird") | Query("wind");
const auto results = q.eval(file);
cout << "\nExecuting Query for: " << q << endl;
print(cout, results) << endl;
infile.close();
return 0;
}
输出:
Executing Query for: ((fiery & bird) | wind)
((fiery & bird) | wind) occurs 3 times
(line 2) Her Daddy says when the wind blows
(line 4) like a fiery bird in flight
(line 5) A beautiful fiery bird he tells her