高级程序设计

18 - 纯虚函数和抽象类

2020-04-02 15:00 CST
2020-04-02 12:46 CST
CC BY-NC 4.0

基类中哪些成员函数需要设计称虚函数?

  • 在设计基类时,有时虽然给出了某些成员函数的实现,但实现的方法可能不是最好,今后可能还会有更好的实现方法。
  • 在基类中根本无法给出某些成员函数的实现,它们必须由不同的派生类根据实际情况给出具体的实现(纯虚函数)。

纯虚函数

纯虚函数是没给出实现的虚函数,函数体用=0表示,如:

class A {
  public:
    virtual int foo() = 0;
};

纯虚函数一般在派生类中给出实现。

抽象类

包含纯虚函数的类称为抽象类,抽象类不能用于创建对象。

抽象类的作用是为派生类提供一个基本框架和一个公共的对外接口。

抽象类 v.s. 联合类型

抽象类的好处:

  • 通过动态绑定调用相应派生类的虚函数
  • 即使增加类派生类的种类,高层代码不需要改动,只需要增加相应的类(低层代码)即可,实现了高层代码的复用。

联合类型的缺点:

  • 空间利用效率不高;
  • 增加新的类别时,需要对程序的分支进行修改。

利用抽象类实现真正的抽象作用

i.e. 防止绕过访问控制

类中对象按顺序存储在内存中,因此有时可以绕过访问控制。例如:

class A {
  private:
    int i, j;
  public:
    void foo();
};
A *p = new A;
p->i = 1;            // Error
p->j = 2;            // Error
*((int *)p) = 1;     // Access to i
*((int *)p + 1) = 2; // Access to j

解决方案:用抽象类实现抽象,通过抽象类指针让编译器不知道指针指向的对象有哪些数据成员。

class Abstract {
  public:
    virtual void foo();
};
Abstract *p = ...; // A的实现不公开
p->i; // Error
p->j; // Error