1. 多态的意义
- 使程序中的数学运算符合常规的数学运算规则,使程序提供更强的表达能力;
- 使得对不同类型的数据有同样的操作语义(程序的重用);
- 重用标识的资源,提高程序的可读性和可理解性。
2. 多态的种类
在程序中多态分为:通用的多态(universal)及特定的多态。
- 其中通用多态包含:参数多态(parametric)和包含多态(inclusion),特点是对数据类型不加限制;允许对不同类型的值执行相同的代码。
- 特定的多态包含:过载多态(overloading)和强制多态(coercion),特点是只对有限数量的类型有效、对不同类型的值可能要执行不同的代码。
2.1. 参数多态(Parametric polymorphism)
- 概念:采用参数化模板,通过给出不同的类型实参,使得一个程序结构有多种类型。
- 例如:Ada中的generic(类属)、C++中的template(模板),二者均支持数据类型和函数的参数多态。
- 从C++的template 结构可以看出:
- 对实参所取的类型不加限制,不同的实参执行的是相同的代码。所以参数多态是一种通用多态。
- 模板的特点有:
- 在一个抽象结构中允许以参数形式来表示可变部分–包括:类型、函数、常数;
- 在编译时(静态)才进行实例化,结果是一个具体的结构(类型、函数等)。
- 类型的实例化(类型→变量)可以静态进行,也可以动态进行,但结果都是一个值。
如以下代码,在.h文件中定义模板类shape时,将类中的变量类型暂时用”T”代替
1 2 3 4 5 6 7 8 9
| template<class T>
class shape { protected: T bottomLength; T height; };
|
然后在.cpp文件中实例化该shape类时再指定变量的类型。如以下代码实例化该shape时分别指定类中的成员变量bottomLength、height的类型为int、double
1 2 3
| shape<int> shape1(); shape<double > shape2();
|
2.2. 包含多态(inclusion polymorphism)
- 概念:同样的操作可用于一个(基)类型及其派生类型。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30
| template<class T>
class shape { public: virtual T getArea() { return (bottomLength * height); } protected: T bottomLength; T height; };
template<class T>
class Parallelogram : public shape<T> { public: };
template<class T>
class Rectangle : public shape<T> { public: };
|
2.3. 重置
类比与之相似的“重置”。如C++中在基类定义的virsual方法,在派生类中再进行不同实现。如以下代码,在.h文件中从基类shape派生了两个子类:Triangle和Rectangle,两个子类中对父类的同一方法getArea()进行了两种不同的再实现,此为C++中的另一种形式的多态(重置)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37
| template<class T>
class shape { public: virtual T getArea() { return (bottomLength * height); } protected: T bottomLength; T height; }; template<class T>
class Triangle : public shape<T> { public: T getArea() { return (this->bottomLength * this->height / 2); } };
template<class T>
class Rectangle : public shape<T> { public: T getArea() { return (this->bottomLength * this->height); } };
|
2.4. 过载多态(overloading polymorphism)
- 概念:同一个表示操作的名字(如操作符、函数名)在不同的上下文中有不同的类型。(相同抽象,不同细节)。
- 程序设计语言中基本类型的多数操作符都是过载多态的。如:一个过载多态的操作符或函数名,它通常对应多个不同的实现。
如以下代码在定义shape类中,有两个shape()构造函数,仅形参不同
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
| template<class T>
class shape { protected: T bottomLength; T height; public: shape() { bottomLength = 0; height = 0; } shape(T value1, T value2) { bottomLength = value1; height = value2; } };
|
2.5. 强制多态(coercion)
- 概念:通过语义操作,把操作数的类型强行加以变换,以符合操作符或函数的要求。
- 程序设计语言中基本类型的大多数操作符,在发生不同类型的数据进行混合运算时,编译程序一般都会进行强制类型转换(强制多态)。这种强制转换通常是隐式的,但程序员也可以显式地进行强制多态的操作(Casting)。
1 2 3 4
| int a=3, b=2; double c; c = a + b;
|
3. 尝试构建一个同时包含四种多态的范例
构造了一个基于C++的包含参数多态、包含多态、过载多态和强制多态的范例, 其中参数多态用模板展现。
3.1. .h文件完整代码如下:
文件名: PolymorphismTest.h1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90
| #ifndef POLYMORPHISMTEST_H_
#define POLYMORPHISMTEST_H_
template<class T>
class shape { protected: T bottomLength; T height; public: shape() { bottomLength = 0; height = 0; } shape(T value) { bottomLength = value; height = value; } shape(T value1, T value2) { bottomLength = value1; height = value2; } virtual T getArea() { return (bottomLength * height); } };
template<class T>
class Triangle : public shape<T> { public: T getArea() { return (this->bottomLength * this->height / 2); } Triangle(T value1, T value2) { this->bottomLength = value1; this->height = value2; } };
template<class T>
class Parallelogram : public shape<T> { public: Parallelogram(T value1, T value2) { this->bottomLength = value1; this->height = value2; } };
template<class T>
class Rectangle : public shape<T> { public: T getArea() { return (this->bottomLength * this->height); } Rectangle(T value1, T value2) { this->bottomLength = value1; this->height = value2; } };
#endif
|
3.2. .cpp文件完整代码如下:
文件名: PolymorphismTest.cpp1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39
| #include <iostream>
#include "PolymorphismTest.h"
using namespace std;
int main(void) {
shape<int> shape1(); shape<double > shape2();
shape<double> shape3(); shape<double> shape4(3.2, 5.7);
shape<double> shape5(4, 5); Parallelogram<double> parallelogram(4, 5); shape5.getArea(); parallelogram.getArea(); int a, b; Rectangle<int> rectangle1(4, 4); Triangle<int> triangle1(4, 4); a = rectangle1.getArea(); b = triangle1.getArea();
double c; c = a + b; cout << c << endl;
return 0; }
|