1. 程式人生 > >c++ primer 第十五章習題

c++ primer 第十五章習題

c++ primer 第十五章習題


練習15.1 派生類需要覆蓋的基類中的virtual成員
練習15.2 protected訪問符定義的成員可以被繼承類的成員函式及友元訪問,private只能被當前類的成員和友元訪問。
練習15.3

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;
};
double print_total(ostream &os, const Quote &item, size_t n) {
	double ret = item.net_price(n);
	os << "ISBN: "<<item.isbn() << " # sold: " << n << " total due: " << ret << endl;
	return ret;
}

練習15.4 (a) 不能繼承自己,是定義不是宣告。 (b) 是定義不是宣告。 ©不需要加繼承關係。
練習15.5

class Bulk_quote:public Quote
{
public:
	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 {
		if(n >= min_qty)
			return n*(1-discount)*price;
		else
			return n*price;
	}

private:
	int min_qty;
	double discount;
};

練習15.7

class Disc_quote:public Quote
{
public:
	Disc_quote(const string& book, double p, size_t qty, double disc):
	Quote(book,p),max_qty(qty),discount(disc) {}

	double net_price(size_t n) const override {
		if(n <= max_qty)
			return n*(1-discount)*price;
		else
			return (n-max_qty)*price+max_qty*(1-discount)*price;
	}

private:
	int max_qty;
	double discount;
};

練習15.8 靜態型別是指編譯時已知的,變數宣告時的型別或者表示式生成的型別。動態型別是指變數或表示式表示的記憶體中的物件的型別,執行時才知道。
練習15.9 使用基類指標或者引用時。
練習15.12 有必要,兩個功能不影響。
練習15.13 有問題,派生類裡呼叫base::print
練習15.14 (a) base (b) derived © base (d) base (e) base (f) derived
練習15.15

class Disc_quote:public Quote
{
public:
	Disc_quote(const string& book, double p, size_t qty, double disc):
	Quote(book,p),quantity(qty),discount(disc) {}

	double net_price(size_t n) const = 0;

protected:
	size_t quantity = 0;
	double discount = 0.0;
};

class Bulk_quote:public Disc_quote
{
public:
	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 {
		if(n >= quantity)
			return n*(1-discount)*price;
		else
			return n*price;
	}

};

練習15.16

class Max_quote:public Disc_quote
{
public:
	Max_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 {
		if(n >= quantity)
			return quantity*(1-discount)*price + (n-quantity)*price;
		else
			return n*(1-discount)*price;
	}

};

練習15.18 T F 不能訪問base公有成員 F同上 T F F
練習15.19 TTTTFT
練習15.23 加個定義;除了bp2->fcn()其它不變。
練習15.24 有繼承類的基類
練習15.25 因為Disc_quote的預設建構函式會執行Quote的預設建構函式,而Quote預設建構函式會完成成員的初始化工作。 如果去除掉該建構函式的話,Bulk_quote的預設建構函式而無法完成Disc_quote的初始化工作。(因為不定義的話在已有建構函式的情況下不會再合成預設建構函式)

練習15.26

#ifndef MYQUOTE_H
#define MYQUOTE_H
#include <iostream>
#include <vector>
#include <string>
#include <memory>

using namespace std;

class Quote {
public:
	Quote() = default;
	friend bool operator !=(const Quote& lhs, const Quote& rhs);
	Quote(const string& book, double sales_price):
	    bookNo(book), price(sales_price) {}
	Quote(const Quote& q):bookNo(q.bookNo),price(q.price){
		cout << "Quote(Quote& q)"<<endl;
	}
	Quote(Quote&& q) noexcept:bookNo(move(q.bookNo)),price(move(q.price)){
		cout << "Quote(Quote&& q)"<<endl;
	}
	Quote& operator=(const Quote& q) {
		if(q != *this) {
			bookNo = q.bookNo;
			price = q.price;
		}
		cout << "Quote& operator=(Quote& q)"<<endl;
		return *this;
	}
	Quote& operator=(Quote&& q) noexcept {
		if(q != *this) {
			bookNo = move(q.bookNo);
			price = move(q.price);
		}
		cout << "Quote& operator=(Quote&& q)"<<endl;
		return *this;
	}
	string isbn() const { return bookNo;}
	virtual double net_price(size_t n) const {
		cout << "Quote::net_price"<<endl;
		return n*price;
	}
	virtual Quote* clone() const &{
		return new Quote(*this);
	}
	virtual Quote* clone() &&{
		return new Quote(move(*this));
	}
	virtual void debug() const{
		cout << "bookNo: "<< bookNo << " price: " << price << endl;
	}
	virtual ~Quote() = default;
private:
	string bookNo;
protected:
	double price = 0.0;
};

bool inline
operator !=(const Quote& lhs, const Quote& rhs)
{
	return lhs.bookNo != rhs.bookNo
		||
		lhs.price != rhs.price;
}
#endif
#ifndef DISC_QUOTE_H
#define DISC_QUOTE_H
#include <iostream>
#include <vector>
#include <string>
#include <memory>
#include "myQuote.h"

using namespace std;
class Disc_quote:public Quote
{
	friend bool operator!=(const Disc_quote&, const Disc_quote&);
public:
	Disc_quote() {
		cout << "Disc_quote()" <<endl;
	}
	Disc_quote(const string& book, double p, size_t qty, double disc):
	Quote(book,p),quantity(qty),discount(disc) {}

	Disc_quote(const Disc_quote& dq):
	Quote(dq.isbn(),dq.price),quantity(dq.quantity),discount(dq.discount){}
	Disc_quote(Disc_quote&& dq) noexcept:
	Quote(dq.isbn(),move(dq.price)),quantity(move(dq.quantity)),discount(move(dq.discount)){}

    Disc_quote& operator=(const Disc_quote& dq) {
    	if(*this != dq) {
    		Quote(dq.isbn(), dq.price);
    		quantity = dq.quantity;
    		discount = dq.discount;
    	}
    	cout << "Disc_quote& operator=(const Disc_quote& dq)" <<endl;
    	return *this;
    }
    Disc_quote& operator=(Disc_quote&& dq) noexcept{
    	if(*this != dq) {
    		Quote(dq.isbn(), move(dq.price));
    		quantity = move(dq.quantity);
    		discount = move(dq.discount);
    	}
    	cout << "Disc_quote& operator=(Disc_quote&& dq)" <<endl;
    	return *this;
    }

    ~Disc_quote() {
    	cout << "~Disc_quote()"<<endl;
    }

	double net_price(size_t n) const = 0;

protected:
	size_t quantity = 0;
	double discount = 0.0;
};

bool inline
operator !=(const Disc_quote& lhs, const Disc_quote& rhs)
{
	return lhs.isbn() != rhs.isbn()||lhs.price != rhs.price
		||lhs.quantity != rhs.quantity || lhs.discount != rhs.discount;
}
#endif
#ifndef BULK_QUOTE_H
#define BULK_QUOTE_H
#include <iostream>
#include <vector>
#include <string>
#include <memory>
#include "Disc_quote.h"

using namespace std;




class Bulk_quote : public Disc_quote
{

public:
	Bulk_quote() { std::cout << "default constructing Bulk_quote\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) noexcept: Disc_quote(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) noexcept
	{
		Disc_quote::operator =(std::move(rhs));
		std::cout << "Bulk_quote : move =()\n";

		return *this;
	}

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

	Quote* clone() const & override {
		return new Bulk_quote(*this);
	}
	Quote* clone() && override {
		return new Bulk_quote(move(*this));
	}
	void  debug() const override{
		cout << "Bulk_quote::debug(): ";
		cout << "bookNo: "<< isbn() << " price: " << price <<"quantity: " << quantity<< "discount: "<<discount<< endl;
	};

	~Bulk_quote()
	{
		cout << "destructing Bulk_quote" <<endl;
	}
};


double print_total(ostream &os, const Quote &item, size_t n) {
	double ret = item.net_price(n);
	os << "ISBN: "<<item.isbn() << " # sold: " << n << " total due: " << ret << endl;
	return ret;
}

#endif

練習15.28 29

int main() {
	Bulk_quote bq("0-3843-3432",3.4, 5, 0.1);
	Bulk_quote bq2("0-3843-3432",3.2, 15, 0.2);
	vector<Quote> v1 = {bq,bq2};
	vector<shared_ptr<Quote>> v2 = {make_shared<Bulk_quote>(bq), make_shared<Bulk_quote>(bq2)};
	double res = 0;
	res = v1[0].net_price(20)+v1[1].net_price(20);
	cout << "vector<Quote> total price: "<< res<<endl;
	res = v2[0]->net_price(20)+v2[1]->net_price(20);
	cout << "vector<make_shared<Quote>> total price: "<< res<<endl;
	return 0;
}

練習15.30

#ifndef MYBASKET_H
#define MYBASKET_H
#include "Bulk_quote.h"
#include <set>


class basket
{
public:
	void add_item(Quote&& sale) {
		items.insert(shared_ptr<Quote>(move(sale).clone()));
	}
	void add_item(const Quote& sale) {
		items.insert(shared_ptr<Quote>(sale.clone()));
	}

	double total_receipt(ostream& os) const {
		double sum = 0;
		for(auto iter = items.begin(); iter != items.end(); iter = items.upper_bound(*iter)) {
			sum += print_total(os,**iter,items.count(*iter));
		}
		os << "Total Sale: " << sum <<endl;
		return sum;
	}
private:
	bool static compare(const shared_ptr<Quote>& a, const shared_ptr<Quote>& b) {
		return a->isbn() < b->isbn();
	}
	multiset<shared_ptr<Quote>,decltype(compare)*> items{compare};
	
};
#endif
int main() {
	Bulk_quote bq("0-3843-3432",3.4, 5, 0.1);
	Bulk_quote bq2("0-3843-3432",3.2, 15, 0.2);
	basket bs;
	bs.add_item(bq);
	bs.add_item(bq2);
	bs.total_receipt(cout);
	return 0;
}