练习15.1:什么是虚成员?
在类中声明为virtual的成员函数,基类希望这种成员函数在派生类中被重新定义。除了构造函数不能被定义为虚成员函数为,其他的任意非static成员函数可以定义为虚成员函数(也就是说析构函数可以定义为虚成员函数)
练习15.2:protected访问说明符与private有何区别?
protected是受保护的访问说明符,意味着被protected声明的成员可以被该类的成员、友元以及该类的派生类成员(非友元)访问,但不能被该类的对象访问。
而private声明的成员,只能被该类的成员和友元访问,该类的派生类不能访问。
练习15.3:定义你自己的Quote类和print_total函数。
class Quote
{
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; //书籍的ISBN编号
protected:
double price=0.0; //代表普通状态下不打折的价格
};
注:此类为书上定义的Quote类。
练习15.4:下面哪条声明语句是不正确的?请说明原因。
class Base { … };
(a) class Derived : public Derived { … };
(b) class Derived : private Base { … };
(c) class Derived : public Base;
(a)不正确,一个类本身不能从自己派生而来
(b)正确
(c)不正确,声明类的时候,不可以包含派生列表,只有在定义类的时候才派生列表。
练习15.5:定义你自己的Bulk_quote类
class Bulk_quote : public Quote
{
public:
double net_price( size_t cnt ) const override
{
if ( cnt >=min_qty )
return cnt * ( 1- discount ) * price;
else
return cnt * price;
}
private:
size_t min_qty;
double discount;
};
练习15.6:将Quote类和Bulk_quote的对象传给15.2.1节(第529页)练习中的print_total函数,检查该函数是否正确。
略。
练习15.7:定义一个类使其实现一种数量受限的折扣策略,具体策略是:当购买书籍的数量不超过一个给定的限量时享受折扣,如果购买量一旦超过了限量,则超出的部分将以原价销售。
class Limited_quote : public Quote
{
public:
double net_price( size_t cnt ) const override
{
if ( cnt <=min_qty )
return cnt * ( 1- discount ) * price;
else
return min_qty*(1-discount)*price+(cnt-min_qty) * price;
}
private:
size_t min_qty;
double discount;
};
练习15.8:给出静态类型和动态类型的定义。
静态类型在编译时就已经确定了,它是变量声明时的类型或表达式生成的类型;而动态类型则是变量或表达式表示的内存中的对象的类型,动态类型直到运行时才能知道。
如:
Quote *pQuote =new Bulk_quote;
指针pQuote的静态类型是Quote,在编译时就已经确定了。但是它的动态类型是Bulk_quote,直到运行时才能知道它指向的是基类还是派生类。
如果一个变量非指针也非引用,则它的静态类型和动态类型永远一致。但基类的指针或引用的动态类型可能与其动态类型不一致。
练习15.9:在什么情况下表达式的静态类型可能与动态类型不同?请给出三个静态类型与动态类型不同的例子。
Bulk_quote bulk;
Quote *pQuote=&bulk;
Quote &rQuote=bulk;
只知道两个,第三个不知道,o(╯□╰)o
练习15.10:回忆我们在8.1节(第279页)进行的讨论,解释第284页中将ifstream传递给Sales_data的read函数的程序是如何工作的。
在要求使用基类型对象的地方,可以使用派生类型的对象来代替。
练习15.11:为你的Quote类体系添加一个名为debug的虚函数,令其分别显示每个类的数据成员。
#include <iostream>
using namespace std;
class Quote
{
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 void debug()
{
cout<<"bookNo="<<bookNo<<" price="<<price<<endl;
}
virtual ~Quote()=default; //对析构函数进行动态绑定
private:
std::string bookNo; //书籍的ISBN编号
protected:
double price=0.0; //代表普通状态下不打折的价格
}