练习15.1 什么是虚成员?
基类希望其派生类进行覆盖的函数,任何构造函数之外的非静态都可以是虚函数。
练习15.2 protected访问说明符与private有何区别?
派生类可以使用基类中protected的成员,而不能使用private中的成员。
练习15.3 定义你自己的Quote类和print_total函数。
#include <iostream>
#include <string>
using namespace std;
class Quote {
friend double print_total(ostream&,const Quote&, size_t);
public:
Quote() = default;
Quote(const std::string &book, double sales_price) :bookNo(book), price(sales_price) {}
std::string isbn() const { return bookNo; }
virtual double net_price(std::size_t n) const { return n*price; }
virtual ~Quote() = default;
private:
std::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 下面哪条声明语句是不正确的?请解释原因。
class Base { ... };
(a) class Derived :public Derived { ... }; //类不能继承自己
(b) class Derived :public private Base { ... }; //正确的,继承Base中的私有成员
(c) class Derived :public Base; //类声明语句不能包含派生列表
15.5 定义你自己的Buik_quote类。
class Bulk_Quote:public Quote {
public:
Bulk_Quote() = default;
Bulk_Quote(const std::string &book, double p, std::size_t qty, double disc) :
Quote(book, p), min_qty(qty), discount(disc) {}
double net_price(std::size_t)const override;
private:
std::size_t min_qty = 0;
double discount = 0.0;
};
double Bulk_Quote::net_price(std::size_t cnt) const
{
if (cnt >= min_qty) {
return cnt*(1 - discount)*price;
}
else
{
return cnt*price;
}
}
练习15.6 将Quote和Bulk_quote的对象传给15.2.1节练习中的print_total函数,检查该函数是否正确。
#include <iostream>
#include <string>
#include "Quote.h"
using namespace std;
int main()
{
Quote item1("C++primer", 89.1);
Bulk_Quote item2("effective c++", 49.9, 5, 0.1);
print_total(cout, item1,10);
print_total(cout, item2,100);
}
练习15.7 定义一个类使其实现一种数量受限的折扣策略,具体策略是:当购买书籍的数量不超过一个给定的限量时享受折扣,如果购买量一旦超过了限量,则超出部分将以原价销售。
改动Bulk_net中的net_price函数。
double Bulk_Quote::net_price(std::size_t cnt) const
{
if (cnt < min_qty) {
return cnt*(1 - discount)*price;
}
else
{
return cnt*(1 - discount)*price + (cnt - min_qty)*price;
}
}
练习15.8 给出静态类型和动态类型的定义。
表达式的静态类型在编译时总是已知的,它是变量声明时的类型或表达式生成的类型。
动态类型则是在变量或表达式表示的内存中的对象的类型。动态类型直到运行时才可知。
练习15.9 在什么情况下表达式的静态类型可能与动态类型不同?请给出三个静态类型与动态类型不同的例子。
基类的指针或引用的静态类型可能与其动态类型不一致。
(a) double ret = item.net_price(n);
(b) double p = item.price;
(c) string s = item.bookNo;
练习15.10 回忆我们在8.1节(279页)进行的讨论,解释第284页中将ifstream传递给Sales_data的read函数的程序是如何工作的。
ifstream继承自istream,当程序运行时,read函数中的对象使用ifstream来传入数据。