当前位置: 首页 > article >正文

C++ Primer第五版_第十五章习题答案(21~30)

文章目录

      • 练习15.21
      • 练习15.22
      • 练习15.23
      • 练习15.24
      • 练习15.25
      • 练习15.26
        • Quote
        • Bulk_quote
      • 练习15.27
      • 练习15.28
      • 练习15.29
      • 练习15.30
        • basket.h
        • basket.cpp
        • main.cpp

练习15.21

从下面这些一般性抽象概念中任选一个(或者选一个你自己的),将其对应的一组类型组织成一个继承体系:

(a) 图形文件格式(如gif、tiff、jpeg、bmp)
(b) 图形基元(如方格、圆、球、圆锥)
(c) C++语言中的类型(如类、函数、成员函数)

练习15.22

对于你在上一题中选择的类,为其添加函数的虚函数及公有成员和受保护的成员。

练习15.23

假设第550页的 D1 类需要覆盖它继承而来的 fcn 函数,你应该如何对其进行修改?如果你修改之后 fcn 匹配了 Base 中的定义,则该节的那些调用语句将如何解析?

移除 int 参数。

练习15.24

哪种类需要虚析构函数?虚析构函数必须执行什么样的操作?

基类通常应该定义一个虚析构函数。

练习15.25

我们为什么为 Disc_quote 定义一个默认构造函数?如果去掉该构造函数的话会对 Bulk_quote 的行为产生什么影响?

因为Disc_quote的默认构造函数会运行Quote的默认构造函数,而Quote默认构造函数会完成成员的初始化工作。 如果去除掉该构造函数的话,Bulk_quote的默认构造函数而无法完成Disc_quote的初始化工作。

练习15.26

定义 Quote 和 Bulk_quote 的拷贝控制成员,令其与合成的版本行为一致。为这些成员以及其他构造函数添加打印状态的语句,使得我们能够知道正在运行哪个程序。使用这些类编写程序,预测程序将创建和销毁哪些对象。重复实验,不断比较你的预测和实际输出结果是否相同,直到预测完全准确再结束。

Quote

#ifndef QUOTE_H
#define QUOTE_H

#include <string>
#include <iostream>

class Quote
{
	friend bool operator !=(const Quote& lhs, const Quote& rhs);
public:
	Quote() { std::cout << "default constructing Quote\n"; }
	Quote(const std::string &b, double p) :
		bookNo(b), price(p)
	{
		std::cout << "Quote : constructor taking 2 parameters\n";
	}

	// copy constructor
	Quote(const Quote& q) : bookNo(q.bookNo), price(q.price)
	{
		std::cout << "Quote: copy constructing\n";
	}

	// move constructor
	Quote(Quote&& q) noexcept : bookNo(std::move(q.bookNo)), price(std::move(q.price))
	{ std::cout << "Quote: move constructing\n"; }

	// copy =
	Quote& operator =(const Quote& rhs)
	{
		if (*this != rhs)
		{
			bookNo = rhs.bookNo;
			price = rhs.price;
		}
		std::cout << "Quote: copy =() \n";

		return *this;
	}

	// move =
	Quote& operator =(Quote&& rhs)  noexcept
	{
		if (*this != rhs)
		{
			bookNo = std::move(rhs.bookNo);
			price = std::move(rhs.price);
		}
		std::cout << "Quote: move =!!!!!!!!! \n";

		return *this;
	}

	std::string     isbn() const { return bookNo; }
	virtual double  net_price(std::size_t n) const { return n * price; }
	virtual void    debug() const;

	virtual ~Quote()
	{
		std::cout << "destructing Quote\n";
	}

private:
	std::string bookNo;

protected:
	double  price = 10.0;
};

bool inline
operator !=(const Quote& lhs, const Quote& rhs)
{
	return lhs.bookNo != rhs.bookNo
		&&
		lhs.price != rhs.price;
}

#endif // QUOTE_H

Bulk_quote

#ifndef BULK_QUOTE_H
#define BULK_QUOTE_H
#include "Disc_quote.h"
#include <iostream>

class Bulk_quote : public Disc_quote
{

public:
	Bulk_quote() { std::cout << "default constructing Bulk_quote\n"; }
	Bulk_quote(const std::string& b, double p, std::size_t q, double disc) :
		Disc_quote(b, p, q, disc)
	{
		std::cout << "Bulk_quote : constructor taking 4 parameters\n";
	}

	// copy constructor
	Bulk_quote(const Bulk_quote& bq) : Disc_quote(bq)
	{
		std::cout << "Bulk_quote : copy constructor\n";
	}

	// move constructor
	Bulk_quote(Bulk_quote&& bq) : Disc_quote(std::move(bq)) noexcept
	{
		std::cout << "Bulk_quote : move constructor\n";
	}

	// copy =()
	Bulk_quote& operator =(const Bulk_quote& rhs)
	{
		Disc_quote::operator =(rhs);
		std::cout << "Bulk_quote : copy =()\n";

		return *this;
	}


	// move =()
	Bulk_quote& operator =(Bulk_quote&& rhs) noexcept
	{
		Disc_quote::operator =(std::move(rhs));
		std::cout << "Bulk_quote : move =()\n";

		return *this;
	}

	double net_price(std::size_t n) const override;
	void  debug() const override;

	~Bulk_quote() override
	{
		std::cout << "destructing Bulk_quote\n";
	}
};

#endif // BULK_QUOTE_H

练习15.27

重新定义你的 Bulk_quote 类,令其继承构造函数。

#ifndef BULK_QUOTE_H
#define BULK_QUOTE_H
#include "disc_quote.h"
#include <iostream>

class Bulk_quote : public Disc_quote
{

public:
	Bulk_quote() { std::cout << "default constructing Bulk_quote\n"; }

	// changed the below to the inherited constructor for ex15.27.
	// rules:  1. only inherit from the direct base class.
	//         2. default, copy and move constructors can not inherit.
	//         3. any data members of its own are default initialized.
	//         4. the rest details are in the section section 15.7.4.
	/*
	Bulk_quote(const std::string& b, double p, std::size_t q, double disc) :
	Disc_quote(b, p, q, disc) { std::cout << "Bulk_quote : constructor taking 4 parameters\n"; }
	*/
	using Disc_quote::Disc_quote;

	// copy constructor
	Bulk_quote(const Bulk_quote& bq) : Disc_quote(bq)
	{
		std::cout << "Bulk_quote : copy constructor\n";
	}

	// move constructor
	Bulk_quote(Bulk_quote&& bq) : Disc_quote(std::move(bq))
	{
		std::cout << "Bulk_quote : move constructor\n";
	}

	// copy =()
	Bulk_quote& operator =(const Bulk_quote& rhs)
	{
		Disc_quote::operator =(rhs);
		std::cout << "Bulk_quote : copy =()\n";

		return *this;
	}


	// move =()
	Bulk_quote& operator =(Bulk_quote&& rhs)
	{
		Disc_quote::operator =(std::move(rhs));
		std::cout << "Bulk_quote : move =()\n";

		return *this;
	}

	double net_price(std::size_t n) const override;
	void  debug() const override;

	~Bulk_quote() override
	{
		std::cout << "destructing Bulk_quote\n";
	}
};



#endif // BULK_QUOTE_H

练习15.28

定义一个存放 Quote 对象的 vector,将 Bulk_quote 对象传入其中。计算 vector 中所有元素总的 net_price。

#include <iostream>
#include <string>
#include <vector>
#include <memory>

#include "quote.h"
#include "bulk_quote.h"
#include "limit_quote.h"
#include "disc_quote.h"


int main()
{
	/**
	* @brief ex15.28   outcome == 9090
	*/
	std::vector<Quote> v;
	for (unsigned i = 1; i != 10; ++i)
		v.push_back(Bulk_quote("sss", i * 10.1, 10, 0.3));

	double total = 0;
	for (const auto& b : v)
	{
		total += b.net_price(20);
	}
	std::cout << total << std::endl;

	std::cout << "======================\n\n";

	/**
	* @brief ex15.29   outccome == 6363
	*/
	std::vector<std::shared_ptr<Quote>> pv;

	for (unsigned i = 1; i != 10; ++i)
		pv.push_back(std::make_shared<Bulk_quote>(Bulk_quote("sss", i * 10.1, 10, 0.3)));

	double total_p = 0;
	for (auto p : pv)
	{
		total_p += p->net_price(20);
	}
	std::cout << total_p << std::endl;

	return 0;

}

练习15.29

再运行一次你的程序,这次传入 Quote 对象的 shared_ptr 。如果这次计算出的总额与之前的不一致,解释为什么;如果一直,也请说明原因。

因为智能指针导致了多态性的产生,所以这次计算的总额不一致。

练习15.30

编写你自己的 Basket 类,用它计算上一个练习中交易记录的总价格。

basket.h

#ifndef BASKET_H
#define BASKET_H

#include "quote.h"
#include <set>
#include <memory>


// a basket of objects from Quote hierachy, using smart pointers.
class Basket
{
public:
	// copy verison
	void add_item(const Quote& sale)
	{
		items.insert(std::shared_ptr<Quote>(sale.clone()));
	}
	// move version
	void add_item(Quote&& sale)
	{
		items.insert(std::shared_ptr<Quote>(std::move(sale).clone()));
	}

	double total_receipt(std::ostream& os) const;

private:

	// function to compare needed by the multiset member
	static bool compare(const std::shared_ptr<Quote>& lhs,
		const std::shared_ptr<Quote>& rhs)
	{
		return lhs->isbn() < rhs->isbn();
	}

	// hold multiple quotes, ordered by the compare member
	std::multiset<std::shared_ptr<Quote>, decltype(compare)*>
		items{ compare };
};

#endif // BASKET_H

basket.cpp

#include "basket.h"
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))
		//  ^^^^^^^^^^^^^^^^^^^^^^^^^^^
		// @note   this increment moves iter to the first element with key
		//         greater than  *iter.

	{
		sum += print_total(os, **iter, items.count(*iter));
	}                                   // ^^^^^^^^^^^^^ using count to fetch
	// the number of the same book.
	os << "Total Sale: " << sum << std::endl;
	return sum;
}

main.cpp

#include <iostream>
#include <string>
#include <vector>
#include <memory>
#include <fstream>

#include "quote.h"
#include "bulk_quote.h"
#include "limit_quote.h"
#include "disc_quote.h"
#include "basket.h"


int main()
{
	Basket basket;

	for (unsigned i = 0; i != 10; ++i)
		basket.add_item(Bulk_quote("Bible", 20.6, 20, 0.3));

	for (unsigned i = 0; i != 10; ++i)
		basket.add_item(Bulk_quote("C++Primer", 30.9, 5, 0.4));

	for (unsigned i = 0; i != 10; ++i)
		basket.add_item(Quote("CLRS", 40.1));

	std::ofstream log("log.txt", std::ios_base::app | std::ios_base::out);

	basket.total_receipt(log);
	return 0;
}

http://www.kler.cn/news/17520.html

相关文章:

  • Spring Boot 整合 Swagger 教程详解
  • ChatGPT写文章效果-ChatGPT写文章原创
  • leetcode 530. 二叉搜索树的最小绝对差
  • 《互联网安全产品漏洞管理规定》
  • 【Linux Network】网络编程套接字
  • 轻松掌握在已有K8s环境上安装KubeSphere
  • 【五一创作】Qt quick基础1(包含基本元素Text Image Rectangle的使用)
  • HTTP加密
  • 身份鉴别解读与技术实现分析(1)
  • 【Linux】多路转接--select、poll、epoll,非阻塞等待
  • 超大excel文件读,避免内存溢出
  • 【华为OD机试真题 Python】简单的解压缩算法 (100%通过)
  • node之Express
  • 【GAMES101】05 Rasterization(Triangles)
  • 【初学人工智能原理】【4】梯度下降和反向传播:能改(下)
  • 算法设计与分析期末复习
  • 判断密码判断密码
  • 删除游戏-类似打家劫舍
  • Canvas和SVG有什么区别?
  • java基础知识——26.反射
  • 架构集群部署
  • 深度学习 -- PyTorch学习 torchvision工具学习 Transforms模块 Normalize用法
  • Db2 hardcode一个CTE
  • 科研人必看入门攻略(收藏版)
  • B017_群函数篇
  • ( 数组和矩阵) 287. 寻找重复数 ——【Leetcode每日一题】
  • Python JSON
  • 网络安全合规-数据安全风险评估
  • 【数据结构】图笔记
  • 【泛函分析】区间上的单调有界函数必存在左右极限,间断点必为第一类间断点