6. 多态

多态(Polymorphism)是不同的对象展现出不同的状态。多态 允许程序使用同一的接口(通常是基类的指针)来操作不同的派生类对象。而具体执行那个类的成员函数则在运行时根据不同的对象来决定。

多态是指使用父类的指针,在指针指向不同的子类对象时,调用的成员函数是子类对象的成员函数。即调用由指向的类型决定,而不是由指针类型决定,这种现象叫做多态。

C++ 中的多态是使用虚(成员)函数来实现的。

虚函数 是指在成员函数声明时使用关键字 virtual 声明的成员函数。

语法

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

说明:

示例

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

using namespace std;

#define PI (3.1415926)
// 点类(描述一个点的位置,面积等信息)
class Point {
    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[]) {
    Point * shapes[4];
    Circle c1(4, 6, 10);
    Point * 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 poly poly.cpp
weimz@mzstudio:~$ ./poly
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
程序结束!

可见 main 函数中的 ps 指针的类型是 Shape* 但因为他指向了不同类型的子类对象,因此 ps->info()ps->getArea() 都调用的不同的成员函数。此现象为多态。

说明