C++中多层继承(inheritance) 的使用及示例

动态绑定只能应用在虚函数(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*/
/*更多精彩内容:http://www.bianceng.cnhttp://www.bianceng.cn/Programming/cplus/*/
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

作者:csdn博客 Spike_King

以上是小编为您精心准备的的内容,在的博客、问答、公众号、人物、课程等栏目也有的相关内容,欢迎继续使用右上角搜索按钮进行搜索string
, include
, ostream
, const
, ifstream
, c++操作word
, shared ptr
, std
, new派生友元基类
, 行号
, 绑定C++类
, shared_ptr加锁
, shared_ptr
多层派生
c多重继承示例、java 多层继承、多层继承、c 多层继承、thinkphp模板多层继承,以便于您获取更多的相关知识。

时间: 2024-09-20 01:07:15

C++中多层继承(inheritance) 的使用及示例的相关文章

C++中的继承(inheritance) 和动态绑定(dynamic binding) 简介

继承(inheritance)和动态绑定(dynamic binding) 是面向对象的重要组成部分, 即继承(inheritance)和多态(polymorphism), 可以使 派生类(derived class)拥有 基类(base class) 的接口(interface); 派生类可以覆写(override)基类的虚函数(virtual function), 符合特定的功能; 派生类可以隐式地转换为基类 (derived-to-base conversion), 但不可逆, 因为派生类

【《Objective-C基础教程 》笔记ch04】(五)OC中的继承inheritance机制

一.为什么需要继承                            使用继承一方面继承了父类的特性,另一方便解决了重复代码维护问题. 二.继承之语法          1. @interface 子类名:父类名          2. OC只支持单继承,不支持继承多个父类.          3. 重构--移植和优化代码. 三. 继承的工作机制           1. 方法调度               子类拥有一个指向它父类的引用指针,消息传递时,OC的方法调度机制使用该信息来找到正

Style在Android中的继承关系

Android的Styles(样式)和Themes(主题)非常类似Web开发里的CSS,方便开发者将页面内容和布局呈现分开.Style和Theme在Android里的定义方式是完全一样的,两者只是概念上的区别:Style作用在单个视图或控件上,而Theme用于Activity或整个应用程序.由于作用范围的不同,Theme也就需要比Style包含更多的定义属性值的项目(item).不过本文,我将Style和Theme都归为Style来称呼. Android的Style和Web的CSS相比,有一个缺

如何用语句去实现多层继承

问题描述 如何用语句去实现多层继承 Person类,有Student类和Employee类继承Person, 而Employee类又被教员类Teacher类和职员类Staff类继承. 每个人都有姓名.地址.电话号码和电子邮件地址. 学生有年级状态(大一到大四). 雇员有办公室(office).工资(salary)和受聘日期(dateOfEmployee). 教员有办公时间(wordTime)和级别(level). 职员有职位(job). 覆盖每个类的toString()方法,显示相应的类名和人名

从一个组件的实现来深刻理解JS中的继承

其实,无论是写什么语言的程序员,最终的目的,都是把产品或代码封装到一起,提供接口,让使用者很舒适的实现功能.所以对于我来说,往往头疼的不是写代码,而是写注释和文档!如果接口很乱,肯定会头疼一整天. JavaScript 最初是以 Web 脚本语言面向大众的,尽管现在出了服务器端的 nodejs,但是单线程的性质还没有变.对于一个 Web 开发人员来说,能写一手漂亮的组件极为重要.GitHub 上那些开源且 stars 过百的 Web 项目或组件,可读性肯定非常好. 从一个例子来学习写组件 组件教

YUI 3中的继承模式及其用法简介

YUI 3中的继承模式及其用法简介 January 6, 2010 at 6:30 am by Stoyan Stefanov 文中讨论了YUI 3 两种代码复用的方式:基于类的继承(classical inheritance pattern)和原型继承(prototypal inheritance)模式. 依赖 在种子文件yui-min.js中就有属于core YUI 3 API 部分的原型模式(prototypal pattern)继承.如果需要类模式(classical pattern)的

在JavaScript中实现继承

javascript|继承 JavaScript脚本语言是一种功能强大的面向对象的语言.本文描述了如何在JavaScript中实现继承. Prototype JavaScript没有实现类继承,但可以通过prototype实现.每个JavaScript类中都包含一个prototype对象,当访问一个对象的属性和方法时,它首先从当前对象查找,如果该属性在JavaScript类定义,则直接访问:否则,从类的prototype对象中查找,如果找到则直接访问,否则从prototype的prototype

C++中如何在容器中使用继承和虚函数

容器不支持混合类型, 如果直接把派生类对象, 存入基类容器中, 则无法使用派生-基转换(derived-base conversion); 因为转换只能发生在指针和引用 过程中, 不能发生在 对象直接赋值, 如果是直接转换, 则会产生截断(sliced down); 即派生类部分被切除, 只留下基类部分; 所以存入容器中的派生类 输出为基类部分 的虚函数; 如果想在容器中, 进行继承, 则需要使用指针, 包括智能指针(如:shared_ptr<>), 则会输出派生类的覆写(override)版

ORM中的继承关系映射全解——单表继承体系、一实体一具体表、一实体一扩展表

ORM中的继承关系映射全解--单表继承体系.一实体一具体表.一实体一扩展表.接口映射 本文涉及的内容包括: 1.单表继承体系 2.一实体一具体表 3.一实体一扩展表 4.接口实现映射vs基类继承映射 1.单表继承体系 所谓单表继承体系就是用一张数据库表存储整个继承体系中的所有实体的数据.单表继承体系适合那种继承体系中实体数目相对较少,总记录数相对较少,子类对父类的属性扩展也相对较少的情形. 单表继承体系优点是读/写继承体系中的每个实体的数据,都只需操作一张表,性能较好,并且,新增继承类,或扩展实