抽象类和纯虚函数

抽象类用于创建通用实体,就是您期待用其创建更具体的派生类。抽象类仅可以作为其他类的基类,这就是为什么不可能创建抽象类类型的对象。

一个至少包含一个纯虚函数的类就是抽象的。因此,源自于抽象类的类必须实现其全部的纯虚函数,否则它也将是抽象类。

虚函数通过使用pure-specifier语法来声明为"pure"。考虑CAnimal 类的示例,创建它只是为了提供普通函数 - CAnimal类型的对象对于实际使用过于一般。因此,CAnimal是抽象类的一个很好的示例:

class CAnimal
  {
public:
                      CAnimal();     // 构造函数
   virtual void       Sound() = 0;   // 纯虚函数
private:
   double             m_legs_count;  // 动物腿的数量
  };

这里Sound() 是一个纯虚函数,因为它是以纯虚函数PURE(=0)说明符进行声明。

纯虚函数只是以PURE说明符设置的虚函数:(=NULL) 或 (=0)。抽象类声明和使用的示例:

class CAnimal
  {
public:
   virtual void       Sound()=NULL;   // PURE 类函数,应该在派生类覆盖,CAnimal现在是抽象类,不能创建
  };
//--- 派生自一个抽象类
class CCat : public CAnimal
 {
public:
  virtual void        Sound() { Print("Myau"); } // PURE被覆盖,CCat不是抽象类,可以创建
 };
 
//--- 错误使用的示例
new CAnimal;         // 'CAnimal'错误 - 编译器返回 "不能示例抽象类"的错误 
CAnimal some_animal; // 'CAnimal'错误 - 编译器返回 "不能示例抽象类"的错误
 
//--- 正确使用的示例
new CCat;  // 无错误 - CCat 不是抽象类
CCat cat;  // 无错误 - CCat 不是抽象类

 
抽象类的限制

如果抽象类的构造函数调用一个纯虚函数(直接或间接),结果是未定义的。

//+------------------------------------------------------------------+
//| 抽象基类                                        |
//+------------------------------------------------------------------+
class CAnimal
  {
public:
   //--- 纯虚函数
   virtual void      Sound(void)=NULL;
   //--- 函数
   void              CallSound(void) { Sound(); }
   //--- 构造函数
   CAnimal()
    {
     //--- 虚类函数的显式调用
     Sound();
     //--- 隐式调用(使用第三个函数)
     CallSound();
     //--- 构造函数和/或析构函数始终调用其自己的函数,
     //--- 即使它们是虚拟的并被派生类调用的函数覆盖
     //--- 如果调用的函数是纯虚函数,
     //--- 其调用将会导致危险的运行时错误:"纯虚函数调用"
    }
  };

然而,对于抽象类的构造函数和析构函数可以调用其他成员函数。