C++Prime 第十五章

C++Prime 第十五章

练习15.1

虚成员:基类希望派生类覆盖的成员函数.任何构造函数之外的非静态函数都可以是虚函数.

练习15.2

protected: 允许派生类访问
private:不允许

练习15.3

#pragma once
#include <iostream>
#include <vector>
using namespace std;
class Quote
{
public:
	Quote() = default;
	Quote(const string& book, double sales_price) :bookNo(book), price(sales_price) {}
	
	string isbn()const { return bookNo; }

	virtual double net_price(size_t n)const { return n * price; }
	virtual ~Quote() = default;	//对析构函数进行动态绑定
private:
	string bookNo;
protected:
	double price = 0.0;
};

class Bulk_quote :public Quote
{
public:
	double net_price(size_t n)const override;
};

double print_total(ostream& os, const Quote& item, size_t n)
{
	//可以调用Quote::net_price
	//也可以调用Bulk_quote::net_price
	double ret = item.net_price(n);
	os << "ISBN" << item.isbn()
		<< " # sold: " << n << " total due: " << ret << endl;
}

练习15.4

(a) 不能派生自己
(b)ok
© 类派生列表不可出现在声明语句中.

练习15.5

#pragma once
#include <iostream>
#include <vector>
using namespace std;
class Quote
{
public:
	Quote() = default;
	Quote(const string& book, double sales_price) :bookNo(book), price(sales_price) {}
	
	string isbn()const { return bookNo; }

	virtual double net_price(size_t n)const { return n * price; }
	virtual ~Quote() = default;	//对析构函数进行动态绑定
private:
	string bookNo;
protected:
	double price = 0.0;
};

class Bulk_quote :public Quote
{
public:
	Bulk_quote() = default;
	Bulk_quote(const string& book, double p, size_t qty, double disc)
		:Quote(book, p), min_qty(qty), discount(disc) { }

	double net_price(size_t n)const override;
private:
	size_t min_qty = 0;//使用折扣政策的最低购买量
	double discount = 0.0;//以小数表示的折扣额
};

double print_total(ostream& os, const Quote& item, size_t n)
{
	//可以调用Quote::net_price
	//也可以调用Bulk_quote::net_price
	double ret = item.net_price(n);
	os << "ISBN" << item.isbn()
		<< " # sold: " << n << " total due: " << ret << endl;
}

练习15.6

int main()
{
	Quote q;
	Bulk_quote bq;
	print_total(cout, q, 3);
	print_total(cout, bq, 4);
	return 0;
}

练习15.7

class my_Bulk_quote :public Bulk_quote
{
public:
	my_Bulk_quote() = default;
	my_Bulk_quote(const string& book, double p, size_t qty, double disc, size_t m)
		:Bulk_quote(book, p, qty, disc), max_qty(m) { }
	double net_price(size_t n)const override;
private:
	size_t max_qty = 0;
};

#include "Quote.h"

double Bulk_quote::net_price(size_t n) const
{
    if (n >= min_qty)
        return n * (1 - discount) * price;
    else
        return n * price;
}

double my_Bulk_quote::net_price(size_t n) const
{
    if (n >= max_qty)
        return (n - max_qty) * price + Bulk_quote::net_price(max_qty);  
    return Bulk_quote::net_price(n);;
}

练习15.8

静态类型:编译时已知,它是变量声明时的类型或表达式生成的类型.
动态类型:运行时才知道,是变量或表达式表示的内存中的对象的类型

练习15.9

基类的指针或引用的静态类型可能和其动态类型不一致.

Quote q1;
Bulk_quote q2;
Quote &p1 = q2;
Quote* p2 = &q2;

练习15.10

ifstream派生自istream,故其对象可以当成istream来使用

练习15.11

int main()
{
	Quote q("倚天屠龙记",10);
	Bulk_quote bq("降魔传",10,20,0.8);
	my_Bulk_quote my_bq("系游", 5, 20, 0.9, 20);
	q.debug();
	cout << endl;

	bq.debug();
	cout << endl;
	my_bq.debug();
	cout << endl;
	return 0;
}
#pragma once
#include <iostream>
#include <vector>
using namespace std;
class Quote
{
public:
	Quote() = default;
	Quote(const string& book, double sales_price) :bookNo(book), price(sales_price) {}
	
	string isbn()const { return bookNo; }

	virtual double net_price(size_t n)const { return n * price; }
	virtual ~Quote() = default;	//对析构函数进行动态绑定

	virtual void debug() { cout << "书名: "<<bookNo << ",单价: " << price; }
private:
	string bookNo;
protected:
	double price = 0.0;
};

class Bulk_quote :public Quote
{
public:
	Bulk_quote() = default;
	Bulk_quote(const string& book, double p, size_t qty, double disc)
		:Quote(book, p), min_qty(qty), discount(disc) { }

	double net_price(size_t n)const override;

	void debug() { 
		Quote::debug();
		cout << ",折扣政策的最低购买量: " << min_qty
			<< ",折扣额: " << discount;
	}
private:
	size_t min_qty = 0;//使用折扣政策的最低购买量
	double discount = 0.0;//以小数表示的折扣额
};

class my_Bulk_quote :public Bulk_quote
{
public:
	my_Bulk_quote() = default;
	my_Bulk_quote(const string& book, double p, size_t qty, double disc, size_t m)
		:Bulk_quote(book, p, qty, disc), max_qty(m) { }
	auto net_price(size_t n) const ->double  override;
	void debug() { Bulk_quote::debug(); cout << ",最大限额量: " << max_qty; }
private:
	size_t max_qty = 0;
};

练习15.12

没有必要.假如是一个大于两层的继承体系.声明override表示将某个成员函数覆盖了,难保该类的派生类(第三层的继承类)不继续覆盖该成员函数,所以如果不是确信不会对其进行覆盖的情况下,不要用final.

练习15.13

有,无限递归,加上类限定符即可

练习15.14

(a)基类
(b)派生类
©基类
(d)派生类
(e)基类
(f)派生类

练习15.15

class Disc_quote :public Quote
{
public:
	Disc_quote() = default;
	Disc_quote(const string& book, double price, size_t qty, double disc)
		:Quote(book, price), quantity(qty), discount(disc) { }
	double net_price(size_t)const = 0;
protected:
	size_t quantity = 0; //折扣适用的购买量
	double discount = 0; //表示折扣的小数值
};

class Bulk_quote :public Disc_quote
{
public:
	Bulk_quote() = default;
	Bulk_quote(const string& book, double p, size_t qty, double disc)
		:Disc_quote(book, p, qty, disc){ }

	double net_price(size_t n)const override;
};
double Bulk_quote::net_price(size_t n) const
{
    if (n >= quantity)
        return n * (1 - discount) * price;
    else
        return n * price;
}

练习15.16

class my_Bulk_quote :public Disc_quote
{
public:
	my_Bulk_quote() = default;
	my_Bulk_quote(const string& book, double p, size_t qty, double disc, size_t m)
		:Disc_quote(book, p, qty, disc), max_qty(m) { }
	auto net_price(size_t n) const ->double  override;
private:
	size_t max_qty = 0;
};
double my_Bulk_quote::net_price(size_t n) const
{
    if (n >= max_qty)
        return (n - max_qty) * price + max_qty * (1 - discount) * price;  
    return n * (1 - discount) * price;;
}

练习15.17

不可以定义纯虚拟基类的对象

练习15.18

Base *p = &d1; //合法,基类指针或引用可以指向公有派生类.
p = &d2; //不合法,基类的指针或引用可以指向公有派生的类对象
p = &d3; //不合法,同上
p = &dd1; //合法,基类指针或引用可以指向公有派生类

练习15.19

Derived_from_private是错误的.
第二层的派生类肯定是毫无问题的,第三层的派生类必须继承自第二层公有或派生的类,才可以向基类转换

练习15.20

正确

int main()
{
	pub_derive d1;
	priv_derive d2;
	prot_derive d3;
	derived_from_private dd2;
	derived_from_public  dd1;
	derived_from_protected dd3;
	myBase* p = &d1;
	//p = &d2;
	//p = &d3;
	p = &dd1;
	//p = &dd2;
	//p = &dd3;

	return 0;
}

练习15.21

练习15.22

#pragma once
#include <iostream>
#include <cmath>
const double PI = 3.141592657;

class Shape//ABC
{
public:
	Shape() = default;										//默认构造函数
																		//其他函数无需定义
	virtual ~Shape() {};										//虚析构函数
public:
	//成员函数
	double get_area() const;								//获得该图形的面积
	virtual void calculate() = 0;							//纯虚函数,计算相关数据
	virtual void debug() const = 0;					//输出所有数据
protected:
	double area = 0;					//面积
};

class Square :public Shape
{
public:
	Square(double n) :side_len(n) { calculate(); }				//使用边长进行构造
	Square() = default;														//默认构造,边长初始化为0
																						//其他拷贝控制函数不需要
	~Square() override { };													//虚析构,不用定义任何操作
public:
	void calculate() override;												//重写
	void debug() const override;										//输出所有数据
	
	double get_perimeter() const;										//获得该图形的周长
private:
	double side_len = 0;					//边长
	double perimeter = 0;					//周长
};

class Round :public Shape
{
public:
	Round() = default;
	Round(double r) :radiu(r) { calculate(); }
	~Round()override { }
public:
	void calculate() override;										//纯虚函数,计算面积和周长
	void debug()const override;

	double get_perimeter() const;								//获得该图形的周长

private:
	double radiu = 0;					//圆的半径
	double perimeter = 0;
};

class Ball :public Shape
{
public:
	//类的基础
	Ball() = default;
	Ball(double r) :radiu(r) { calculate(); }
	~Ball()override { }
public:
	//功能实现
	void calculate()override;												//计算
	void debug()const override;

	double get_volumn()const;											//获得球的体积

private:
	double radiu = 0;						//半径
	double volumn = 0;					//体积
};

class Cone :public Shape
{
public:
	Cone() = default;
	Cone(double r, double h) :radiu(r), height(h) { calculate(); }
	~Cone() override { }
public:
	void calculate()override;
	void debug() const override;
	double get_volumn();

private:
	double radiu = 0;
	double height = 0;
	double volumn = 0;
	double mother_line = 0;
};

#include "Shape.h"

void Square::calculate()
{
    area = side_len * side_len;
    perimeter = 4 * side_len;
    return;
}

void Square::debug() const
{
    std::cout << "这是个方块!边长是: " << side_len
        << ",周长是: " << perimeter
        << ",面积是: " << area
        << std::endl;
}



double Square::get_perimeter() const
{
    return perimeter;
}

double Shape::get_area() const
{
    return area;
}



void Round::calculate()
{
    area = PI * radiu * radiu;
    perimeter = 2 * PI * radiu;
    return;
}

void Round::debug() const
{
    std::cout << "这是个圆!半径是: " << radiu
        << ",周长是: " << perimeter
        << ",面积是: " << area
        << std::endl;
}

double Round::get_perimeter() const
{
    return perimeter;
}

void Ball::calculate()
{
    area = 4 * PI * radiu * radiu;
    volumn = PI * radiu * radiu * radiu * 4 / 3;
    return;
}

void Ball::debug() const
{
    std::cout << "这是个球!半径是: " << radiu
        << ",面积是: " << area
        <<",体积是: "<<volumn
        << std::endl;
}

double Ball::get_volumn() const
{
    return volumn;
}

void Cone::calculate()
{
    mother_line = sqrt(height * height + radiu * radiu);
    area = PI * radiu * mother_line + PI * radiu * radiu;
    volumn = PI * radiu * radiu * height / 3;
    return;
}

void Cone::debug() const
{
    std::cout << "这是个圆锥!半径是: " << radiu
        <<",高度是: "<<height
        <<",母线长是: "<<mother_line
        << ",体积是: " << volumn
        << ",面积是: " << area << std::endl;
}

double Cone::get_volumn()
{
    return volumn;
}

int main()
{
	Square s(2);	
	Round r(3);
	Ball b(4);
	Cone c(6, 7);

	vector<Shape* > pvec{&s,&r,&b,&c};//基类指针可以指向公有派生类对象
	for (auto p : pvec)
		p->debug();

	return 0;
}

输出:

这是个方块!边长是: 2,周长是: 8,面积是: 4
这是个圆!半径是: 3,周长是: 18.8496,面积是: 28.2743
这是个球!半径是: 4,面积是: 201.062,体积是: 268.083
这是个圆锥!半径是: 6,高度是: 7,母线长是: 9.21954,体积是: 263.894,面积是: 286.882

练习15.23

去掉形参int.
Base bobj; D1 d1obj; D2 d2obj;
Base *bp1 = &bobj, *bp2 = &d1obj, *bp3 = &d2obj;

bp1->fcn(); //调用Base::fcn
bp2->fcn(); //调用Base::fcn()
bp3->fcn(); //调用D2::fcn

bp2->f2(); //报错,Base没有成员函数f2()
d1p->f2(); //调用D1::f2()
d2p->f2(); //调用D2::f2()

p1->fcn(42); //报错,base没有成员函数fcn(int)
p2->fcn(42); //报错,(未修改前不报错)
p3->fcn(42); //调用D2::fcn(int)

练习15.24

继承体系中的类分配了资源,该基类必须定义虚析构函数.
释放所分配的资源.

练习15.25

如果不给Disc_quote定义一个默认的构造函数,那么因为定义了自定义的构造函数,Disc_quote将没有默认构造函数.
那么它的派生类的默认构造函数将是被删除的.
将无法使用默认构造函数.

练习15.26

#pragma once
#include <iostream>
#include <vector>
using namespace std;
class Quote
{
public:
	Quote(const Quote& q) ;
	Quote(Quote&& q) ;
	Quote& operator=(const Quote& q) ;
	Quote& operator=(Quote&& q);

public:
	Quote(const string& book = " ", double sales_price = 0.0) :bookNo(book), price(sales_price) { cout << "使用Quote的构造函数\n"; }
	
	string isbn()const { return bookNo; }

	virtual double net_price(size_t n)const { return n * price; }
	virtual ~Quote() = default;	//对析构函数进行动态绑定

	virtual void debug() { cout << "书名: "<<bookNo << ",单价: " << price; }
private:
	string bookNo;
protected:
	double price = 0.0;
};

class Disc_quote :public Quote
{
public:
	Disc_quote(const Disc_quote& d);
	Disc_quote(Disc_quote&& d);
	Disc_quote& operator=(const Disc_quote& d);
	Disc_quote& operator=(Disc_quote && d);

public:
	Disc_quote() = default;
	Disc_quote(const string& book, double price, size_t qty, double disc)
		:Quote(book, price), quantity(qty), discount(disc) { }
	double net_price(size_t)const = 0;
protected:
	size_t quantity = 0; //折扣适用的购买量
	double discount = 0; //表示折扣的小数值
};

class Bulk_quote :public Disc_quote
{
public:
	Bulk_quote() = default;
	Bulk_quote(const string& book, double p, size_t qty, double disc)
		:Disc_quote(book, p, qty, disc){ }

	double net_price(size_t n)const override;
};

class my_Bulk_quote :public Disc_quote
{
public:
	my_Bulk_quote() = default;
	my_Bulk_quote(const string& book, double p, size_t qty, double disc, size_t m)
		:Disc_quote(book, p, qty, disc), max_qty(m) { }
	auto net_price(size_t n) const ->double  override;
	//void debug() { Bulk_quote::debug(); cout << ",最大限额量: " << max_qty; }
private:
	size_t max_qty = 0;
};

练习15.27

练习15.28

练习15.29

	vector<shared_ptr<Quote> > v;
	v.push_back(make_shared<Bulk_quote>("0-123-12", 50, 10, 0.25));
	v.push_back(make_shared<Bulk_quote>("0-sdf", 20, 15, 0.27));
	double sum = 0;
	for (const auto& p : v)
		sum += p->net_price(8);
	cout << sum << endl;

练习15.30

#pragma once
#include <vector>
#include <iostream>
#include <set>
#include "Quote.h"
using namespace std;
class Basket
{
public:

	void add_item(const Quote& sales) {
		items.insert(shared_ptr<Quote>(sales.clone()));
	}
	void add_item(Quote&& sales) {
		items.insert(shared_ptr<Quote>(std::move(sales).clone()));
	}

	void add_item(const shared_ptr<Quote>& sale) { items.insert(sale); }
	double total_receipt(ostream&)const;
private:
	static bool compare(const shared_ptr<Quote> &lhs, const shared_ptr<Quote>& rhs )
	{
		return lhs->isbn() < rhs->isbn();
	}
	multiset<shared_ptr<Quote>, decltype(compare)* > items{ compare };
};

练习15.31

(a)Query(s1)生成一个WordQuery对象.然后生成一个OrQuery,右侧先生成WordQuery,然后变成NotQuery,最后生成一个AndQuery
(b)先生成WordQuery,然后NOtQuery,然后AndQuery最后NotQuery

练习15.32

最后一个例子及其剩下的题目暂时不做了,很久很久后会来补上的.

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值