时间:2014.04.25
地点:基地
----------------------------------------------------------------------------------------
一、纯虚函数
与普通虚函数相比,纯虚函数无须定义。在函数体位置即分号之前赋值为0就可以了。要注意的是=0这种形式也只能在类内部的虚函数声明之处。看一个例子:
class DiscQuote:public Quote{
public:
DisQuote()=default;
DisQuote(const std::string& book,double price,std::size_t qty,double disc):
Quote(book,price),quantity(qty),discount(disc){}
double net_price(std::size_t) const=0;
proctected:
std::sie_t quantity=0;
double discount=0.0;
};
在这里,这个继承下来的类是不能直接定义这个类的对象的,我们将使用它派生出对象,并借助于它的构造函数构建DiscQuote部分。默认构造函数将对该部分执行默认初始化,接受四个参数的构造函数则使用了列表初始化规则初始化成员。net_price在这里是一个纯虚函数,赋值为0,当然也可以为这个纯虚函数提供定义,但应该在类的外部,类的内部是不能为纯虚函数提供定义的。
----------------------------------------------------------------------------------------
二、抽象基类
含有纯虚函数的类称为抽象基类。这包括显式含有纯虚函数的类和或含有未经覆盖直接继承有纯虚函数的类都是抽象基类,即ABC,抽象基类通常负责定义接口,后继的其他类可以覆盖(实现)这个接口。我们也不能直接创建一个抽象基类的对象,即抽象基类一般不能被实例化。抽象基类除非给自己的纯虚函数提供了定义,否则永远都是抽象基类,不能被实例化。记住我们不能创建抽象基类的对象就可以了。
----------------------------------------------------------------------------------------
三、派生类和基类
派生类构造函数只能初始化直接基类。比如:
class BulkQuote:public DiscQuote
{
public:
BulkQuote()=default;
BulkQuote(const std::string& book,double price,std::size_t qty,double disc):DiscQuote(book,price,qty,disc){}
double net_price(std::size_t) const overide;
};
BulkQuote的直接基类是DiscQuote,间接基类是Quote,这样每个BulkQuote对象都含三个子对象,一个是空的BulkQuote部分,一个是DiscQuote部分,一个是Quote部分。
虽然BulkQuote没有自己的数据成员,但还是需要提供能够接受四个参数的构造函数,将实参传给直接基类DiscQuote的构造函数,DiscQuote的构造函数会继续调用Quote的构造函数,初始化bulk的bookNo和price等数据成员,Quote的构造函数结束后,开始执行DiscQuote的构造函数初始化quantity和discount等数据成员,最后运行BulkQuote的构造函数,该函数无须执行实际的初始化工作等。
这是一种重构的思想:即重新设计类的体系以便将操作或数据从一个类移动到另一个类。重构是得原来的体系并不发生变化,也无须改动原来的代码。大大减少了工作量。