多态(polymorphism)
一.多态性:即多种形式或形态的情形。在面向对象方法中,向不同的对象发送同一消息,不同的对象在接收时会产生不同的行为。也就是说,不同的对象用自己的方式去响应共同的消息。
二.多态的类型。
静态多态又称为静态链编或早绑定,编译器在编译阶段完成的,编译器根据函数实参的类型(可能会进行隐式类型转换),可推析出要调用哪个函数,如果有对应的函数就调用该函数,否则编译出错。
动态多态又称为动态链编或晚绑定,即在程序运行阶段判断所引用对象的实际类型,根据其实际类型调用相应的函数。而动态多态是通过虚函数来实现的。
虚函数:在类的成员函数前加virtual关键字,则该成员函数即为一个虚函数,然后在该类的派生类中重新定义该函数。在程序运行期间,用一个基类的指针指向某一派生类的对象,就能通过该指针调用指针指向的派生类对象中的函数。
动态多态的实现:1、基类必须有虚函数,且派生类要重写基类的虚函数。
2、通过基类类型的指针或引用调用虚函数。
虚函数的使用:
1、在基类中用virtual修饰成员函数为虚函数,类外定义虚函数时不必在加关键字virtual。
2、派生类重写基类中的虚函数实现多态,要求函数名,参数列表和返回值完全相同。(除协变)协变:仅函数的返回值不同,基类返回基类的指针或引用,派生类返回派生类的指针或引用。
3、只有类的非静态成员函数才能声明为虚函数,静态成员函数、构造函数、赋值运算符重载和友元函数均不能声明为虚函数。
4、不要在构造函数和析构函数中调用虚函数,此时的对象是不完整的,可能会出现未定义的行为。
5、构造函数不能声明为虚函数而析构函数最好声明为虚函数
请查阅博客http://blog.youkuaiyun.com/better_jh/article/details/53134767
6、当成员函数被声明为虚函数后,其派生类中的同名函数都自动成为虚函数。一般在派生类中重写是最好显示地写出virtual,使程序更加清晰。
程序示例1:
三.继承体系中同名成员函数的关系
四.纯虚函数
在成员函数的形参后面写上 =0,则该成员函数为纯虚函数。包含纯虚函数的类叫做抽象类(或接口类)。抽象类不能实例化出对象。纯虚函数只有在派生类中重定义后派生类才能实例化出对象。
程序示例2:
五.虚表
对于有虚函数类,编译器都会维护一张虚表,对象的前四个字节就是指向虚表的指针。虚表中存放的是虚函数的地址。虚函数按照其声明顺序存放在虚表中。在派生类中,前面是继承基类的虚函数,若派生类重写了基类中的虚函数则替换为重写后的,派生类自己的虚函数追加在其后。如果派生类继承了两个基类,则派生类自己的虚函数追加到第一个继承的基类的虚表的后面。
注:同一个类的对象共用一张虚表。
程序示例3:
六.各种虚函数重写情况的虚表剖析及对象模型:
1、单继承没有虚函数重写:
2、单继承有虚函数重写:
3、多重继承(没有虚函数重写)
4、多重继承(有虚函数重写)
5、菱形继承
6、菱形虚拟继承