跳转至

多态

多态的概念: - 不同对象接收到统一消息时会产生不同行为 - 简单来说,就是在哦同一个类或继承体系结构的基类与派生类中,用同名函数来实现不同的功能

多态与继承的关系: - 继承所处理的是类与类之间的层次关系问题 - 多态处理的是类的层次结构之间以及同一个类内部同名函数的关系问题通常是指继承结构中基类和派生类之间通过同名虚函数实现不同函数功能 的问题。

单接口,多实现

类型: - 重载多态: - 函数重载:同名函数参数不同 - 运算符重载:运算符的操作数类型不同 - 模板多态:通过一个模板生成不同的函数和类 - 继承多态:(一般指这个) - 虚函数:基类指针或引用指向派生类对象时,调用派生类的虚函数 - 接口:通过接口实现多态

多态的实现: - 要有继承 - 派生类要覆盖(重定义)基类的虚函数,即派生类具有和基类函数数据原型完全相同的虚函数成员 - 把基类的指针或引用绑定到派生类对象上

也就是说,没有继承,或者没有派生类没有重定义基类的虚函数, 或者具备前两者,但直接把派生类对象赋值给基类对象(没有通 过指针或引用),都不能实现多态。

多态的实现

class Animal { // 不知道动物会怎么叫!
    public: virtual void sound() { cout << "unknow!" << endl; }
};
class Dog :public Animal { // 狗儿叫声“汪汪汪!”
    public: void sound() { cout << "wang,wang,wang!" << endl; }
};
class Cat :public Animal { // 猫儿叫声“”喵喵喵!
    public: void sound() { cout << "miao,miao,miao!" << endl; }
};
class Wlof :public Animal { // 狼嚎叫声“”!
    public: void sound() { cout << "wu,wu,wu!" << endl; }
};

多态是指当基类的指针(或引用)绑定到派生类对象上,通过此指针(引用)调用基 类的成员函数时,实际上调用到的是该函数在派生类中的覆盖函数版本。

例如,对于上面的继承结构,下面的pa实现的就是多态:

void main() {
Animal *pA;
Dog dog;
Cat cat;
Wlof wlof;
pA = &dog; pA->sound(); //pA 调用 Dog 的 sound 函数
pA = &cat; pA->sound(); //pA 调用 Cat 的 sound 函数
pA = &wlof; pA->sound(); //pA 调用 Wlof 的 sound 函数
}

更一般地,多态更多地体现在用基类对象的指针或引用作为函数的参数,通过它 调用派生类对象中的覆盖函数版本。

例如,针对 Animal 继承体系,设计 animalSound 函数管理每种动物的声音,多态 能够很好地实现此需求。

void animalSound(Animal &animal) {
    animal.sound(); // 调用 Animal 的 sound 函数
}

Animal *pA;
Dog dog;
Cat cat;
Wlof wlof;
animalSound(dog); // 调用 Dog 的 sound 函数
animalSound(cat); // 调用 Cat 的 sound 函数
animalSound(wlof); // 调用 Wlof 的 sound 函数

即以基类 Animal 的引用为接口,可以访问到图 5-1 所示继承体系中 Animal 类的任 何派生类对象的 sound 函数。

多态与联编

一个程序常常会调用到来自于不同文件或 C++ 库中的资源(如函数、对话框) 等,需要经过编译、连接才能形成为可执行文件,

在这个过程中要把调用函数名与对应函数(这些函数可能来源于不同的文件或 库)关联在一起,这个过程就是绑定( binding ),又称联编。

  • 静态联编(静态绑定)
    • 是指在编译程序时就根据调用函数提供的信息,把 它所对应的具体函数确定下来,即在编译时就把调用函数名与具体函数绑定在一起。
  • 动态联编(动态绑定)
    • 是指在编译程序时还不能确定函数调用所对应的具体函数,只有在程序运行过程中才能够确定函数调用所对应的具体函数,即在程序运行时才把调用函数名与具体函数绑定在一起。

多态性的实现方式

  • 编译时多态性:系统在编译时就决定如何实现某一动作 , 即对某一消息如何处理。静态联编具有执行速度快的优点。
    • 函数重载
    • 运算符重载
  • 运行时多态性:系统在运行时才决定如何实现某一动作,即对某一消息如何处理。动态联编具有灵活性和可扩展性。
    • 虚函数
    • 继承

Question

alt text

虚函数