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;
}