C++ Primer 学习笔记_72_面向对象编程 --句柄类与继承[续]

面向对象编程

--句柄类与继承[]



三、句柄的使用

使用Sales_item对象能够更easy地编写书店应用程序。代码将不必管理Item_base对象的指针,但仍然能够获得通过Sales_item对象进行的调用的虚行为。



1、比較两个Sales_item对象

在编写函数计算销售总数之前,须要定义比較Sales_item对象的方法。要用Sales_item作为关联容器的keyword,必须能够比較它们。关联容器默认使用keyword类型的小于操作符,可是假设给Sales_item定义小于操作符,将使其含义不明;

幸好,关联容器使我们能够指定一个函数[或函数对象]用作比較函数。并且,在定义容器对象时必须提供比較函数。

定义一个函数用于比較Sales_item对象:

inline bool
compare(const Sales_item &lsh,const Sales_item &rhs)
{return lsh -> book() < rhs -> book();
}

该函数使用Sales_item->操作符,该操作符返回Item_base对象的指针,哪个指针用于获取并执行成员的book操作,该成员返回ISBN



2、使用带比較器的关联容器

对于比較函数,它必须作为容器的一部分而存储,不论什么在容器中添加�或查找元素的操作都要使用比較函数。

要有效地工作,关联容器须要对每一个操作使用同一比較函数。然而,期望用户每次记住比較函数是不合理的,尤其是,没有办法检查每一个调用使用同一比較函数。因此,容器记住比較函数是有意义的。通过将比較器存储在容器对象中,能够保证比較元素的每一个操作将一致地进行。

为了存储比較器,它须要知道比較器类型。形參类型也不须要与 key_type全然匹配,应该同意能够转换为key_type的随意形參类型。

所以,要使用Sales_item的比較函数,在定义multiset必须指定比較器类型。在我们的样例中,比較器类型是接受两个constSales_item 引用并返回bool值的函数。

    typedef bool (*Comp)(const Sales_item &,const Sales_item &); 

Comp定义为函数类型指针的同义词,该函数类型与我们希望用来比較 Sales_item对象的比較函数相匹配

接着须要定义multiset,保存Sales_item类型的对象并在它的比較函数中使用这个Comp类型。关联容器的每一个构造函数使我们能够提供比較函数的名字

能够这样定义使用compare函数的空multiset:

    std::multiset<Sales_item,Comp> items(compare);

这个定义是说,items是一个multiset,它保存Sales_item对象并使用Comp类型的对象比較它们。multiset是空的—— 我们没有提供不论什么元素,但我们的确提供了一个名为compare的比較函数。当在items添加�查找元素,compare函数multiset进行排序。



3、容器与句柄类

我们定义一个Basket类,用以跟踪销售并计算购买价格:

class Basket
{typedef bool (*Comp)(const Sales_item &,const Sales_item &);
public:typedef multiset<Sales_item,Comp> set_type;typedef set_type::size_type size_type;typedef set_type::const_iterator const_iter;Basket():items(compare) {}void add_item(const Sales_item &item){items.insert(item);}size_type size(const Sales_item &i) const{return items.count(i);}double total() const;private:multiset<Sales_item,Comp> items;
};

该类定义了一个构造函数,即Basket默认构造函数。该类须要自己的默认构造函数,以便将compare传递给建立items成员的multiset构造函数



4、使用句柄执行虚函数

Basket类中的total函数用于返回购物篮中全部物品的价格:

double Basket::total() const
{double sum = 0.0;for (set_type::iterator iter = items.begin();iter != items.end();iter = items.upper_bound(*iter)){sum += (*iter) -> net_price(items.count(*iter));}return sum;
}

   for循环中的“增量”表达式非常有意思。与读每一个元素的一般循环不同,我们推进iter指向下一个键。调用upper_bound函数以跳过与当前键匹配的全部元素,upper_bound函数的调用返回一个迭代器,该迭代器指向与iter键同样的最后一个元素的下一元素,,该迭代器指向集合的末尾或下一本书。測试iter的新值,假设与items.end()相等,则跳出for循环,否则,就处理下一本书。

   我们使用multisetcount成员确定multiset中的多少成员具有同样的键(,同样的isbn),并且使用该数目作为实參调用net_price函数。

for循环的循环体调用net_price函数,阅读这个调用须要一点技巧:

		sum += (*iter) -> net_price(items.count(*iter)); 

iter解引用获得基础Sales_item对象,对该对象应用Sales_item类重载的箭头操作符,该操作符返回句柄所关联的基础Item_base对象的指针,用该Item_base对象指针调用net_price函数,传递具有同样isbn的图书的count作为实參。net_price虚函数,所以调用的定价函数的版本号取决于基础Item_base对象的类型


//P511 习题15.35
//1 in item.h
#ifndef ITEM_H_INCLUDED
#define ITEM_H_INCLUDED#include <string>
#include <utility>class Item_base
{
public:Item_base(const std::string &book = "",double sales_price = 0.0):isbn(book),price(sales_price) {}std::string book() const{return isbn;}virtual double net_price(std::size_t n) const{return price * n;}virtual Item_base *clone() const{return new Item_base(*this);}virtual ~Item_base() {}private:std::string isbn;protected:double price;
};class Disc_item : public Item_base
{
public:Disc_item(const std::string &book = "",double sales_price = 0.0,std::size_t qty = 0,double disc_rate = 0.0):Item_base(book,sales_price),quantity(qty),discount(disc_rate) {}virtual double net_price(std::size_t ) const = 0;std::pair<std::size_t,double> discount_policy() const{return std::make_pair(quantity,discount);}protected:std::size_t quantity;double discount;
};class Bulk_item : public Disc_item
{
public:Bulk_item(const std::string &book = "",double sales_price = 0.0,std::size_t qty = 0,double disc_rate = 0.0):Disc_item(book,sales_price,qty,disc_rate) {}virtual double net_price(std::size_t n) const{if (n >= quantity){return n * (1 - discount) * price;}else{return n * price;}}virtual Bulk_item *clone() const{return new Bulk_item(*this);}
};class Lds_item : public Disc_item
{
public:Lds_item(const std::string &book = "",double sales_price = 0.0,std::size_t qty = 0,double disc_rate = 0.0):Disc_item(book,sales_price,qty,disc_rate) {}virtual double net_price(std::size_t n) const{if (n <= quantity){return n * (1 - discount) * price;}else{return n * price - quantity * discount * price;}}virtual Lds_item *clone() const{return new Lds_item(*this);}
};#endif // ITEM_H_INCLUDED

//2 in sales_item.h
#ifndef SALES_ITEM_H_INCLUDED
#define SALES_ITEM_H_INCLUDED#include "item.h"
#include <stdexcept>class Sales_item
{
public:Sales_item():p(0),use(new std::size_t(1)) {}Sales_item(const Item_base &rhs):p(rhs.clone()),use(new std::size_t(1)) {}Sales_item(const Sales_item &rhs):p(rhs.p),use(rhs.use){++ *use;}~Sales_item(){decr_use();}Sales_item &operator=(const Sales_item &rhs);const Item_base *operator->() const{if (p){return p;}else{throw std::logic_error("unbound Sales_item");}}const Item_base &operator*() const{if (p){return *p;}else{throw std::logic_error("unbound Sales_item");}}private:Item_base *p;std::size_t *use;void decr_use(){if (-- *use){delete p;delete use;}}
};#endif // SALES_ITEM_H_INCLUDED

//3 in sales_item.cpp
#include "sales_item.h"Sales_item &Sales_item::operator=(const Sales_item &rhs)
{++ * rhs.use;decr_use();p = rhs.p;use = rhs.use;return *this;
}

//4 in basket.h
#ifndef BASKET_H_INCLUDED
#define BASKET_H_INCLUDED#include "sales_item.h"
#include <set>inline bool
compare(const Sales_item &lhs,const Sales_item &rhs)
{return lhs -> book() < rhs -> book();
}class Basket
{typedef bool (*Comp)(const Sales_item &,const Sales_item &);
public:typedef std::multiset<Sales_item,Comp> set_type;typedef set_type::size_type size_type;typedef set_type::const_iterator const_iter;Basket():items(compare){}void add_item(const Sales_item &item){items.insert(item);}size_type size(const Sales_item &item) const{return items.count(item);}double total() const;private:std::multiset<Sales_item,Comp> items;};#endif // BASKET_H_INCLUDED

//5 in basket.cpp
#include "basket.h"double Basket::total() const
{double sum = 0.0;for (set_type::iterator iter = items.begin();iter != items.end();iter = items.upper_bound(*iter)){sum += (*iter) -> net_price(items.count(*iter));}return sum;
}

//6 in main.cpp
#include <iostream>
#include "item.h"
#include "basket.h"using namespace std;int main()
{Basket basket;Sales_item item1(Bulk_item("7-115-14554-7",99,20,0.2));Sales_item item2(Item_base("7-115-14554-7",39));Sales_item item3(Lds_item("7-115-14554-7",50,200,0.2));Sales_item item4(Bulk_item("7-115-14554-7",99,20,0.2));basket.add_item(item1);basket.add_item(item2);basket.add_item(item3);basket.add_item(item4);cout << basket.total() << endl;
}

转载于:https://www.cnblogs.com/blfshiye/p/3764203.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/493188.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

《科学》评出2018年度十大科学突破事件

来源&#xff1a;科学大院《科学》杂志每年会评出在即将过去的一年里最为重要的十大科学突破&#xff08;Science Breakthrough&#xff09;。今年&#xff0c;夺得年度突破桂冠的是“单细胞水平细胞谱系追踪技术”&#xff0c;帮助破获多起悬案的法医系谱技术、#MeToo 运动等也…

递归理解以及时间复杂度计算

一.复杂度分析&#xff1a; 可以理解为递归的深度就是空间复杂度&#xff0c;时间复杂度就是O(T*depth),其中&#xff34;是每个递归函数的时间复杂度&#xff0c;depth是递归深度&#xff0e; #空间复杂度O(1) def sum1_(n):res 0for i in range(n1):resireturn res#递归 空…

性价比高出英特尔45%,亚马逊的云服务器芯片如何做到?| 解读

来源&#xff1a;TheNextPlatform编译&#xff1a;机器之能 张玺摘要&#xff1a;到目前为止&#xff0c;亚马逊和其他大型云运营商几乎全部使用英特尔的 Xeon 芯片。虽然在服务器芯片市场&#xff0c;英特尔市场占有率非常高&#xff0c;但亚马逊正使用折扣策略来赢得客户。亚…

将MyEclipse项目导入到Eclipse中

1.请首先确保你的eclipse是javaee版本的&#xff0c;或者已经安装wtp插件2.然后修改eclipse工程下的.project文件&#xff1a;3.在<natures></natures>中加入<nature>org.eclipse.wst.common.project.facet.core.nature</nature> <nature>org.e…

GIOU loss+DIOU loss+CIOU loss

一.IOU 1.GIOU解决没有交集的框,IOU为0,其损失函数导数为0,无法优化的问题。 图1 GIOU,IOU,l2范数差异 a)可看出 l2值一样,IOU值是不一样的,说明L1,L2这些Loss用于回归任务时&#xff0c;不能等价于最后用于评测检测的IoU. b)可看出当框有包含关系,GIOU就退化为IOU 其是找…

《科学》十大年度科学突破反映的新动向

来源&#xff1a;新华网摘要&#xff1a;从测定分子结构到宇宙探索&#xff0c;从发现远古动物到揭示细胞的秘密&#xff0c;美国权威学术刊物《科学》杂志评选的2018年十大科学突破&#xff0c;在时间和空间尺度上拓宽着人类认知的边界&#xff0c;也反映了近年来科学发展的三…

ctpn论文阅读与代码

代码地址: https://github.com/zonghaofan/ctpn_torch 1.通用的目标检测是封闭的,而文字是封闭且连续 2. 构造一系列宽度相等的小文本,回归中心y坐标和高度 3. 对于边界回归x坐标,在进一次修正 4.整个模型就是backbone提取特征,将每个像素点的相邻3*3像素拉成行向量,利用空间…

yum配置与使用

yum配置与使用(很详细) yum的配置一般有两种方式&#xff0c;一种是直接配置/etc目录下的yum.conf文件&#xff0c;另外一种是在/etc/yum.repos.d目录下增加.repo文件。一、yum的配置文件$ cat /etc/yum.conf [main]cachedir/var/cache/yum #yum下载的RPM包的缓存目录k…

新技术不断涌现,下一代云计算的突破口在哪里?

来源&#xff1a;日知录技术社区这是一个IT技术飞速发展的时代&#xff0c;在硬件基础设施的不断升级以及虚拟化网络等技术的日益成熟下&#xff0c;云厂商也正面临着各种新技术带来的巨大挑战。从数据中心的基础建设到云平台的系统构建再到产品底层的技术改革&#xff0c;该如…

生成高斯热力图(craft中有使用)+2d heatmap+3d heatmap

一.生成高斯热力图 from math import exp import numpy as np import cv2 import osclass GaussianTransformer(object):def __init__(self, imgSize512, region_threshold0.4,affinity_threshold0.2):distanceRatio 3.34scaledGaussian lambda x: exp(-(1 / 2) * (x ** 2))…

POP动画[1]

POP动画[1] pop动画是facebook扩展CoreAnimation的,使用及其方便:) 1:Spring系列的弹簧效果(两个动画kPOPLayerBounds与kPOPLayerCornerRadius同时运行) #import "RootViewController.h" #import "YXEasing.h" #import "POP.h" #import "YX…

远比5G发展凶猛!物联网2018白皮书,国内规模已达1.2万亿

来源&#xff1a;智东西摘要&#xff1a;研判物联网的技术产业进展情况&#xff0c;梳理消费物联网、智慧城市物联网、生产性物联网三类物联网应用现状及驱动因素 。在供给侧和需求侧的双重推动下&#xff0c;物联网进入以基础性行业和规模消费为代表的第三次发展浪潮。 5G、 低…

收缩分割多边形(PSENet中有使用)

目的:为了解决密集文本的分割问题 代码: # -*- codingutf-8 -*- import os import cv2 import Polygon as plg import pyclipper import numpy as npdef dist(a, b):return np.sqrt(np.sum((a - b) ** 2))#计算周长 def perimeter(bbox):peri 0.0for i in range(bbox.shape[…

Android 3D emulation 架构理解

Android Emulator 给用户提供 GPU on 选项&#xff0c;意思是利用 Host ( 就是执行 Emulator 的PC机) 的 GPU. 当然PC机必须把 OpenGL 的驱动装好 在实现上就是把 libGLESv1_CM.so libGLESv2.so 替换掉&#xff0c;当system调用 gl的函数的时候&#xff0c;把调用打包为strea…

年度回顾:2018年的人工智能/机器学习惊喜及预测19年的走势

来源&#xff1a;网络大数据考虑到技术变革的速度&#xff0c;我认为让专业IT人士分享他们对2018年最大惊喜及2019年预测的看法会很有趣。以下是他们对人工智能(AI)&#xff0c;机器学习( ML)和其他数据科学迭代的看法&#xff1a;CLARA分析公司首席执行官兼创始人&#xff1a;…

利用dbnet分割条形码与文字(代码+模型)+知识蒸馏+tensorrt推理+利用pyzbar和zxing进行条形码解析

一.DBnet 1.代码链接 分割条形码与文字代码:github链接:GitHub - zonghaofan/dbnet_torch: you can use dbnet to detect word or bar code,Knowledge Distillation is provided,also python tensorrt inference is provided.&#xff08;提供模型&#xff09; 2.论文阅读 …

菜根谭#132

青天白日的节义&#xff0c;自暗室漏屋中培来&#xff1b; 旋乾转坤的经纶&#xff0c;自临深渊履薄处操出。转载于:https://www.cnblogs.com/star4knight/p/3777156.html

全球值得关注的11家人脸识别公司与机构

来源&#xff1a;资本实验室根据美国国家标准与技术研究院&#xff08;NIST&#xff09;的2018年全球人脸识别算法测试&#xff08;FRVT&#xff09;最新结果&#xff0c;今年共有来自全球的39家企业和机构参与本次竞赛。在最新排名中&#xff0c;前五名算法被中国公司包揽&…

图论基础知识--最小生成树算法kruskal(克鲁斯克尔)和普里姆算法(Prim算法);最短路径算法Dijkstra(迪杰斯特拉)和Floyd(弗洛伊德)

一.基础知识 有向图 无向图 以无向图为例: 邻接矩阵: 度矩阵(对角矩阵): 二&#xff0e;最小生成树 应用&#xff1a;将网络顶点看着城市&#xff0c;边看着城市之间通讯网&#xff0c;边的权重看着成本&#xff0c;根据最小生成树可以构建城市之间成本最低的通讯网&#x…

高中生活--第7篇–我为什么不交作业

无耻的打个广告&#xff1a;小伙伴&#xff0c;有IT相关的问题来这里提问吧&#xff0c;http://www.itfriend.cn/topic&#xff0c;社区网友和我努力帮你解答。好久没有写“高中生活”系列了&#xff0c;上一篇“高中生活--第6篇-批评和表扬之间的对决”已经是2013年8月26日。人…