当程序被编译时,表达式ADD(i1, i2)和ADD(s1, s2)分别被替换为两个整数相加和两个字符串相加的具体表达式。整数相加体现为求和,而字符串相加则体现为连接。程序的输出结果符合直觉:
1 + 2 = 3 Hello, + world! = Hello, world!
动态多态
这就是众所周知的的多态。现代面向对象语言对这个概念的定义是一致的。其技术基础在于继承机制和虚函数。例如,我们可以定义一个抽象基类Vehicle和两个派生于Vehicle的具体类Car和Airplane:
// dynamic_poly.h
#include <iostream>
// 公共抽象基类Vehicle class Vehicle { public: virtual void run() const = 0; };
// 派生于Vehicle的具体类Car class Car: public Vehicle { public: virtual void run() const { std::cout << "run a car/n"; } };
// 派生于Vehicle的具体类Airplane class Airplane: public Vehicle { public: virtual void run() const { std::cout << "run a airplane/n"; } };
客户程序可以通过指向基类Vehicle的指针(或引用)来操纵具体对象。通过指向基类对象的指针(或引用)来调用一个虚函数,会导致对被指向的具体对象之相应成员的调用:
// dynamic_poly_1.cpp
#include <iostream> #include <vector> #include "dynamic_poly.h"
// 通过指针run任何vehicle void run_vehicle(const Vehicle* vehicle) { vehicle->run(); // 根据vehicle的具体类型调用对应的run() }
int main() { Car car; Airplane airplane; run_vehicle(&car); // 调用Car::run() run_vehicle(&airplane); // 调用Airplane::run() }
此例中,关键的多态接口元素为虚函数run()。由于run_vehicle()的参数为指向基类Vehicle的指针,因而无法在编译期决定使用哪一个版本的run()。在运行期,为了分派函数调用,虚函数被调用的那个对象的完整动态类型将被访问。这样一来,对一个Car对象调用run_vehicle(),实际上将调用Car::run(),而对于Airplane对象而言将调用Airplane::run()。
或许动态多态最吸引人之处在于处理异质对象集合的能力:
// dynamic_poly_2.cpp
#include <iostream> #include <vector> #include "dynamic_poly.h"
// run异质vehicles集合 void run_vehicles(const std::vector<Vehicle*>& vehicles) { for (unsigned int i = 0; i < vehicles.size(); ++i) { vehicles[i]->run(); // 根据具体vehicle的类型调用对应的run() } }
int main() { Car car; Airplane airplane; std::vector<Vehicle*> v; // 异质vehicles集合 v.push_back(&car); v.push_back(&airplane); run_vehicles(v); // run不同类型的vehicles }
在run_vehicles()中,vehicles[i]->run()依据正被迭代的元素的类型而调用不同的成员函数。这从一个侧面体现了面向对象编程风格的优雅。 
说明:本教程来源互联网或网友上传或出版商,仅为学习研究或媒体推广,wanshiok.com不保证资料的完整性。
2/2 首页 上一页 1 2 |