6. 多态
多态(Polymorphism)是不同的对象展现出不同的状态。多态 允许程序使用同一的接口(通常是基类的指针)来操作不同的派生类对象。而具体执行那个类的成员函数则在运行时根据不同的对象来决定。
多态是指使用父类的指针,在指针指向不同的子类对象时,调用的成员函数是子类对象的成员函数。即调用由指向的类型决定,而不是由指针类型决定,这种现象叫做多态。
C++ 中的多态是使用虚(成员)函数来实现的。
虚函数 是指在成员函数声明时使用关键字 virtual 声明的成员函数。
语法
class 类名{
// 声明是加virtual, 实现时不用加virtual.
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() 都调用的不同的成员函数。此现象为多态。
说明
- C++ 多态是运行时动态的选择调用的成员函数(不是在编译阶段确定的)。