8. 纯虚函数和抽象类

纯虚函数 是指在类内只有存虚函数声明但一定没有实现的虚成员函数。

语法

class 类名{
    // 声明是加virtual,  不用实现
    virtual 返回类型 成员函数名(形式参数列表)=0;
};

纯虚函数的作用是声明一个虚成员函数,继承此类的子类必须实现并覆盖此纯虚函数,如果子类不进行覆盖并实现此纯虚函数则子类对象则不能创建该类的对象。

抽象类

类内包含纯虚函数的类称为抽象类(或纯虚类),抽象类并不能用来创建对象。抽象类仅用来派生子类,要求派生自抽象类的子类则必须重写并实现这些纯虚函数,否则不能创建该类的对象。

抽象类的主要作用是定义接口规范,让此抽象类的子类创建的对象都有统一的成员函数(接口),通过这些成员函数可以统一调用,又根据多态的原理实现个性化的功能。

定义一个抽象类如下:

class Shape{ // 抽象类(Abstract Class);
    public:
        // 纯虚函数的声明
        virtual void moveTo(float x, float y)=0; 
        virtual void info(void) =0;
        virtual float getArea(void) =0; 
};

则派生自此类的子类则必须要重写这三个成员函数,即该类的子类一定有这三个成员函数。

示例

// filename: abstract_cls.cpp
#include <iostream>

using namespace std;

#define PI (3.1415926)
// 抽象类 
class Shape{ // 抽象类(Abstract Class);
    public:
        // 纯虚函数的声明
        virtual void moveTo(float x, float y)=0; 
        virtual void info(void) =0;
        virtual float getArea(void) =0; 
};
// 点类(描述一个点的位置,面积等信息)
class Point: public Shape {
    public:
        Point(float ax=0, float ay=0):x(ax), y(ay) {
            cout << "Point(" << x << "," << y << ")\n";
        }
        // 定义为虚函数
        virtual void info(void) {
            cout << "点(" << x << "," << y << ")\n";
        }
        void moveTo(float new_x, float new_y) {
            x = new_x; y = new_y;
        }
        // 定义为虚函数
        virtual float getArea(void) {
            return 0;
        }
    public:
        float x;
        float y;
};
// 圆类(描述圆的位置、半径、面积等信息)
class Circle : public Point {
    public:
        Circle(float ax, float ay, float radius)
            : Point(ax, ay), r(radius) {
            //  x = ax; y = ay; r = radius;
            cout << "Circle(" << x << "," << y << "," << r << ")\n";
        }
        void info(void) {  // 子类的此函数也为虚函数
            cout << "圆(" << x << "," << y << "," << r << ")\n";
        }
        void showBaseInfo(void) {
            // 显式调用Point类的info 而非自己的info函数
            Point::info();
        }
        float getArea(void) {
            return PI*r*r;
        }
    public:
        float r; // 半径
};
// 定义一个矩形类(长方形)
class Rect : public Point {
    public:
        Rect(int ax, int ay, int aw, int ah)
            : Point(ax, ay), w(aw), h(ah) {
                cout << "Rect(" << x << ","
                    << y << ", " << w << ", "
                    << h << ")\n";
            }
        void info(void) { // 子类的此函数也为虚函数
            cout << "长方形(" << x << ","
                << y << ", " << w << ", "
                << h << ")\n";
        }
        float getArea(void) { // 虚函数
            return w * h;
        }
    protected:
        int w; // 宽
        int h; // 高
};

int main(int argc, char * argv[]) {
    // Shape s; // 报错,抽象类不能创建对象
    Shape * shapes[4];
    Circle c1(4, 6, 10);
    Shape * ps;

    shapes[0] = new Rect(1, 2, 3, 4);
    shapes[1] = &c1;
    shapes[2] = new Point(8, 9);
    shapes[3] = new Circle(10, 11, 12);
    for (int i = 0; i < 4; i++) {
        ps = shapes[i];
        ps->info();
        cout << ps->getArea() << endl;
    }
    cout << "程序结束!" << endl;
    return 0;
}

编译和运行结果如下:

weimz@mzstudio:~$ g++ -o abstract_cls abstract_cls.cpp
.weimz@mzstudio:~$ ./abstract_cls
Point(4,6)
Circle(4,6,10)
Point(1,2)
Rect(1,2, 3, 4)
Point(8,9)
Point(10,11)
Circle(10,11,12)
长方形(1,2, 3, 4)
12(4,6,10)
314.159
点(8,9)
0(10,11,12)
452.389
程序结束!