抽象类和纯虚函数
抽象类用于创建通用实体,就是您期待用其创建更具体的派生类。抽象类仅可以作为其他类的基类,这就是为什么不可能创建抽象类类型的对象。
一个至少包含一个纯虚函数的类就是抽象的。因此,源自于抽象类的类必须实现其全部的纯虚函数,否则它也将是抽象类。
虚函数通过使用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();
//--- 构造函数和/或析构函数始终调用其自己的函数,
//--- 即使它们是虚拟的并被派生类调用的函数覆盖
//--- 如果调用的函数是纯虚函数,
//--- 其调用将会导致危险的运行时错误:"纯虚函数调用"
}
};
|
然而,对于抽象类的构造函数和析构函数可以调用其他成员函数。