多态

来源:互联网 发布:林黛玉 知乎 编辑:程序博客网 时间:2024/06/07 19:52

1、多态引入–数据的类型
数据类型在数据结构中的定义是一个值的集合以及定义在这个值集上的一组操作。变量是用来存储值的所在处,它具有名字和数据类型。变量的数据类型决定了如何将代表这些值的位存储到计算机的内存中。
对象的类型:
静态数据类型 对象声明时的类型。在编译期间就可确定。
动态数据类型 目前所指对象的内容,是在运行期间才确定的。
举例
2、多态
所谓多态,就是多种形态。不同的对象收到相同的消息时,产生不同的执行结果。就是说有两个函数,同名,但是参数列表不同。能根据不同的参数传递实现不同的功能。也就是所谓的“一个接口。多种方法”。
静态多态:函数重载、模板。编译时的多态性,编译时的多态性是通过重载来实现的。对于非虚的成员来说,系统在编译时,根据传递的参数,返回的类型等信息决定实现何种操作

动态多态:虚函数。运行时的多态性,运行时的多态性就是指直到系统运行时,才根据实际情况决定实现何种操作,C++中,运行时的多态性则通过虚成员实现
多态的作用:多态的目的是为了接口重用,也就是说,不论传递过来的究竟是哪个类的对象,函数都能够通过同一个接口调用到适应各自对象的实现方法。
认识虚函数、虚表
C++中的虚函数的主要作用是实现多态。简单来说父类的的指针/引用调用重写的虚函数,当父类指针/引用指向父类对象时调用的是父类的虚函数,指向子类时调用的是子类的虚函数;C++中用虚表来实现多态。虚函数表是通过一块连续内存来存储虚函数的地址。这张表解决了继承,虚函数(重写)
虚函数要点:在c++中基类的对象指针可以指向它公有派生的对象,但是但是当其指向公有派生类对象时,他只能访问派生类中从基类继承来的成员,而不能访问公有派生类中定义的成员。使用virtual关键字修饰类的成员函数时,指明该函数为虚函数,派生类需要重新实现,编译器将实现动态绑定。

#include<iostream>using namespace std;class Base{public:    Base(int x, int y)//构造函数    {        a = x;        b = y;    }    virtual void show()//虚函数    {        cout << "Base::" << a << " " << b << endl;    }private:    int a;    int b;};class Derived:public Base{public:    Derived(int x, int y, int z):Base(x, y)//派生类的构造函数(为基类构造函数传参)    {        c = z;    }    void show()//重新定义虚函数show    {        cout << "Derived::" << c << endl;    }private:    int c;};int main(){    Base b(30, 40);   //创建基类对象b    Base *pb;   //创建基指针类pb    Derived d(10, 20, 30);   //创建派生类对象d    pb = &b;   //对象指针指向基类对象b    pb->show();   //调用基类的虚函数show()    pb = &d;   //对象指针指向派生类对象d    pb->show();   //调用派生类的虚函数show()    system("pause");    return 0;}

运行结果
动态绑定条件
1、必须是虚函数
2、通过基类类型的引用或者指针调虚函数
两个条件必须同时满足才能形成动态绑定
虚函数总结:
1>由于虚函数使用的基础是赋值兼容规则,而赋值兼容规则的前提条件是派生类从其基类公有派生,所以使用虚函数来实现多态时,派生类必须从它的基类公有派生2>必须在基类中定义虚函数
3>在派生类中对基类声明的虚函数进行重定义时,关键字virtual可以加也可以不加,为了不引起混乱,最好加上。
4>虽然使用对象名和点运算符的方式也可以调用虚函数,但只有通过基类指针或引用访问虚函数时才能获得运行时的多态性。
5>一个虚函数无论被继承多少次,它仍然保持其虚函数的特性
6>虚函数必须是所在类的成员函数,而不能是友元函数,也不能是静态成员函数
7>内联函数不能是虚函数,因为内联函数是不能在运行中动态确定其位置的。
8>构造函数不能是虚函数,但虚构函数可以是虚函数

这里写图片描述

协变:
在C++中,
未完待续

原创粉丝点击