c/c++ 继承与多态 容器与继承2 巩固了容器里放智能指针的用法,但是有个问题,对于使用Basket类的用户来说,必须添加的是智能指针,如果能直接添加一个普通的类的对象的话,用起来就方便的多了,所以改进一下Basket类的add_item接口。

新的接口:一个是拷贝给定的对象,另一个是移动对象。

void add_item(const Quote& sale);//左值拷贝
void add_item(Quote&& sale);//右值移动

关键点:

1,由于类Quote没有自定义的拷贝控制成员(拷贝构造函数,赋值语句等),所以,编译器才能自动生成移动构造函数,后面要用到编译器生成移动构造函数。

2,由于key是智能指针,所以在方法add_item里必须要有new,问题来了,new谁呢,只能new父类Quote,但是new了Quote后,子类部分就被切除掉了。

3,为了解决在2处的问题,在Quote和它的子类里添加辅助的虚函数,来得到正确的指针。得到了正确的普通指针就可以用普通指针做出智能指针了。

Quote4.h

#ifndef __QUOTE4_H__
#define __QUOTE4_H__ #include <iostream> class Quote{
public:
Quote() = default;
Quote(const std::string& book, double pri)
:bookNo(book), price(pri){}
std::string isbn() const{return bookNo;} //调用此方法的对象是左值的时候
virtual Quote* clone() const & {
//调用合成的拷贝构造函数
return new Quote(*this);
} ///调用此方法的对象是右值的时候
virtual Quote* clone() && {
//调用合成的移动构造函数
return new Quote(std::move(*this));
} virtual double net_price(std::size_t n)const{
return n * price;
}
virtual void debug()const{
std::cout << bookNo << " " << price << std::endl;
}
virtual ~Quote() = default;
private:
std::string bookNo;
protected:
double price = 0.0;
}; class Disc_quote : public Quote{
public:
Disc_quote() = default;
Disc_quote(const std::string& book, double price,
std::size_t qyn, double disc):Quote(book, price),
quantity(qyn), discount(disc){} double net_price(std::size_t) const override = 0;
protected:
std::size_t quantity = 0;//折扣适用的数量
double discount = 0.0; //折扣率
}; class Bulk_quote : public Disc_quote{
public: Bulk_quote() = default; Bulk_quote(const std::string& book, double price,
std::size_t qyn, double disc)
:Disc_quote(book, price, qyn, disc){} //调用此方法的对象是左值的时候
Bulk_quote* clone() const & {
//调用合成的拷贝构造函数
return new Bulk_quote(*this);
} ///调用此方法的对象是右值的时候
Bulk_quote* clone() && {
//调用合成的移动构造函数
return new Bulk_quote(std::move(*this));
} double net_price(std::size_t) const override;
}; class Min_quote : public Disc_quote{
public: Min_quote() = default;
Min_quote(const std::string& book, double price,
std::size_t qyn, double disc)
:Disc_quote(book, price, qyn, disc){} double net_price(std::size_t) const override;
}; #endif

Quote4.cpp

#include "Quote4.h"

double Bulk_quote::net_price(std::size_t cnt) const{
if(cnt >= quantity){
return cnt * (1 - discount) * price;
}
else{
return cnt * price;
}
} double Min_quote::net_price(std::size_t cnt) const{
if(cnt < quantity){
return cnt * (1 - discount) * price;
}
else{
return cnt * price;
}
}

Basket2.h

#ifndef __BASKET2_H__
#define __BASKET2_H__
#include "Quote4.h"
#include <set>
#include <memory> class Basket{
public:
/*
void add_item(const std::shared_ptr<Quote>& sale){
items.insert(sale);
}
*/ void add_item(const Quote& sale){
items.insert(std::shared_ptr<Quote>(sale.clone()));
}
void add_item(Quote&& sale){
items.insert(std::shared_ptr<Quote>(std::move(sale).clone()));
} double total_receipt(std::ostream&) const;
private:
static bool compare(const std::shared_ptr<Quote>& lhs,
const std::shared_ptr<Quote>& rhs){
return lhs->isbn() < rhs->isbn();
}
std::multiset<std::shared_ptr<Quote>, decltype(compare)*>
items{compare};
}; #endif

Basket2.cpp

#include "Basket.h"

double print_total(std::ostream& os,
const Quote& item, size_t n);
double Basket::total_receipt(std::ostream& os) const{
double sum = 0.0;
for(auto iter = items.cbegin();
iter != items.cend();
iter = items.upper_bound(*iter)){
sum += print_total(os, **iter, items.count(*iter));
}
os << "Total Sale: " << sum << std::endl;
return sum;
}

main.cpp

#include "Quote4.h"
#include "Basket2.h"
#include <vector>
#include <iostream> double print_total(std::ostream& os,
const Quote& item, size_t n){
double ret = item.net_price(n);
os << "ISBN: " << item.isbn()
<< " # sold: " << n << " total due: " << ret << std::endl;
return ret; } int main(){
Basket bsk;
Quote q1("01", 100);
Bulk_quote bq1("01", 100, 2, 0.1);
bsk.add_item(Quote("01", 100)); bsk.add_item(Bulk_quote("01", 100, 2, 0.1)); bsk.total_receipt(std::cout);
}

c/c++ 学习互助QQ群:877684253

本人微信:xiaoshitou5854

c/c++ 继承与多态 容器与继承3的更多相关文章

  1. c/c++ 继承与多态 容器与继承2

    c/c++ 继承与多态 容器与继承1说明了容器里使用继承关系的方法,这里再弄一个练习,巩固一下. 做一个类Basket,它有个multiset成员,key是智能指针std::shared_ptr< ...

  2. c/c++ 继承与多态 容器与继承1

    问题:类B公有继承类A,类A有虚函数fun,类B覆盖了虚函数fun,有一个std::vector<A>,添加A的对象a,和B的对象b,到这个容器里,然后从vector里取出来,使用对象a. ...

  3. lua面向对象实现(实例化对象、继承、多态、多继承、单例模式)

    lua面向对象实现: 一个类就像是一个创建对象的模具.有些面向对象语言提供了类的概念,在这些语言中每个对象都是某个特定类的实例.lua则没有类的概念,每个对象只能自定义行为和形态.不过,要在lua中模 ...

  4. c/c++ 继承与多态 友元与继承

    问题1:类B是类A的友元类,类C是类B的友元类,那么类C是类A的友元类吗?函数fun是类B的友元函数,那么fun是类A的友元函数吗? 都不是,友元关系不能传递. 问题2:类B是类A的友元类,类C是类B ...

  5. Java学习笔记 07 接口、继承与多态

    一.类的继承 继承的好处 >>使整个程序架构具有一定的弹性,在程序中复用一些已经定义完善的类不仅可以减少软件开发周期,也可以提高软件的可维护性和可扩展性 继承的基本思想 >>基 ...

  6. Java的三大特性:封装、继承、多态

    一.类的概念: 类一般包括两个部分:属性(成员变量)和方法(成员方法)方法组成部分:修饰符(可选) 返回值类型(必须) 方法名(必须)参数列表(可选) package com.classTest.pr ...

  7. Java类的继承与多态特性-入门笔记

    相信对于继承和多态的概念性我就不在怎么解释啦!不管你是.Net还是Java面向对象编程都是比不缺少一堂课~~Net如此Java亦也有同样的思想成分包含其中. 继承,多态,封装是Java面向对象的3大特 ...

  8. Python面向对象:继承和多态

    继承与多态简介: 继承可以把父类的所有功能都直接拿过来,这样就不必重零做起,子类只需要新增自己特有的方法,也可以把父类不适合的方法覆盖重写. 动态语言的鸭子类型特点决定了继承不像静态语言那样是必须的. ...

  9. Java入门系列(三)面向对象三大特性之封装、继承、多态

    面向对象综述 封装 封装的意义,在于明确标识出允许外部使用的所有成员函数和数据项,或者叫接口. 有了封装,就可以明确区分内外,使得类实现者可以修改封装内的东西而不影响外部调用者:而外部调用者也可以知道 ...

随机推荐

  1. Python数据挖掘指南

    Data Mining in Python: A Guide 转载原文:https://www.springboard.com/blog/data-mining-python-tutorial/(全英 ...

  2. 优化之Aggregator组件

    Aggregator组件通常会降低性能,因为它们必须在处理数据之前对数据进行分组 Aggregator组件需要额外的内存来保存中间组结果 通过如下方式对Aggregator组件进行优化 简化group ...

  3. Kubernetes系列之监控Metres-server实战篇

    本次系列使用的所需部署包版本都使用的目前最新的或最新稳定版,安装包地址请到公众号内回复[K8s实战]获取 介绍 从 Kubernetes 1.8 开始,Kubernetes 通过 Metrics AP ...

  4. [Abp 源码分析]一、Abp 框架启动流程分析

    Abp 不一定仅用于 Asp.Net Core 项目,他也可以在 Console 与 WinFrom 项目当中进行使用,所以关于启动流程可以分为两种,一种是 Asp.Net Core 项目的启动流程, ...

  5. 使用Genymotion遇到的坑_Genymotion无法启动_unable to start the virtual device

    Genymotion 十分好用,以下是我使用Genymotion碰到的问题及解决办法.目前没有看到网上有完整的解决. 遇到如下图的问题: 这个问题很多人可能回去百度“the virtual devic ...

  6. Python进阶:迭代器与迭代器切片

    2018-12-31 更新声明:切片系列文章本是分三篇写成,现已合并成一篇.合并后,修正了一些严重的错误(如自定义序列切片的部分),还对行文结构与章节衔接做了大量改动.原系列的单篇就不删除了,毕竟也是 ...

  7. 【Java基础】【18Map集合&模拟斗D主X排和F排】

    18.01_集合框架(Map集合概述和特点) A:Map接口概述 查看API可以知道: 将键映射到值的对象 一个映射不能包含重复的键 每个键最多只能映射到一个值 B:Map接口和Collection接 ...

  8. msf登陆Windows 2

    使用ms17_010(永恒之蓝)进行攻击登陆(XP) 1)加载模块 2)连接靶机 3)设置payload 4)设置lhost(攻击主机IP) 5)exploit进行攻击登陆

  9. Real Developer 应该参加的硬核竞赛来了!

    本文由云+社区发表 Labs Contest 竞赛简介 君君这次又来搞大事情啦,在 Function As A Service,Serverless,PaaS 大行其道的今天,你是否已经忘记了自己动手 ...

  10. Joda-Time开源库

    Joda-Time是一个面向 Java™ 平台的易于使用的开源时间日期库. 依赖 <dependency> <groupId>joda-time</groupId> ...