C++ 多态理解

多态

什么是多态????

其实也可以说是一种接口,多种实现方法。

C++ 多态理解_第1张图片

分为静态多态和动态多态。

静态多态分为函数重载和泛型编程,也可以说是静态联编,在编译期间就可以确定了。

函数重载主要是函数的参数列表的不同(数据类型的不同和参数个数的不同)

泛型编程就是建立一个模板,输入不同的数据类型也可以实现想要的功能。

动态多态,也可以说是动态联编,根据虚函数调用不同的函数,根据函数调用的动态绑定。

这是因为每个有虚函数的类或者虚继承的子类,编译器都会为它生成一个虚拟函数表(简称:虚表),表中的每一个元素都指向一个虚函数的地址。(注意:虚表是从属于类的) 

1、构造函数能不能作为虚函数呢?

构造函数的作用我们都知道,是创建对象的,而虚函数的调用是通过对象来进行的,这是矛盾的,所以说构造函数不能声明成虚函数。

2、静态成员函数可以声明成虚函数吗?

如果定义成静态成员函数,那么在这个函数可以通过类名和域作用符来调用,也就是说,不用创建对象就可以调用。

虚表地址的使用必须通过对象的地址才能获取。

重点是:!!!!虚表是通过对象实现的,绕开它或者冲突都会报错

3、析构函数最好声明成虚函数,为什么?

析构函数声明成虚函数的时候,会有效的避免内存泄漏(忘了Delete 子类的析构函数)。

注意:!!!

不要在构造函数和析构函数中调用虚函数!因为在构造函数和析构函数中对象是不完整的,调用虚函数可能会出现未定义的问题!

纯虚函数

您可能想要在基类中定义虚函数,以便在派生类中重新定义该函数更好地适用于对象,但是您在基类中又不能对虚函数给出有意义的实现,这个时候就会用到纯虚函数。

虚表!!!

编译器对每个包含虚函数的类创建一个虚函数表VTABLE,表中每一项指向一个虚函数的地址,即VTABLE表可以看成一个函数指针的数组,每个虚函数的入口地址就是这个数组的一个元素。

每个含有虚函数的类都有各自的一张虚函数表VTABLE。每个派生类的VTABLE继承了它各个基类的VTABLE,如果基类VTABLE中包含某一项(虚函数的入口地址),则其派生类的VTABLE中也将包含同样的一项,但是两项的值可能不同。如果派生类中重载了该项对应的虚函数,则派生类VTABLE的该项指向重载后的虚函数,如果派生类中没有对该项对应的虚函数进行重新定义,则使用基类的这个虚函数地址。

在创建含有虚函数的类的对象的时候,编译器会在每个对象的内存布局中增加一个vptr指针项,该指针指向本类的VTABLE。在通过指向基类对象的指针(设为bp)调用一个虚函数时,编译器生成的代码是先获取所指对象的vtb1指针,然后调用vtb1所指向类的VTABLE中的对应项(具体虚函数的入口地址)。

当基类中没有定义虚函数时,其长度=数据成员长度;派生类长度=自身数据成员长度+基类继承的数据成员长度;

当基类中定义虚函数后,其长度=数据成员长度+虚函数表的地址长度;派生类长度=自身数据成员长度+基类继承的数据成员长度+虚函数表的地址长度。

包含一个虚函数和几个虚函数的类的长度增量为0。含有虚函数的类只是增加了一个指针用于存储虚函数表的首地址。

派生类与基类同名的虚函数在VTABLE中有相同的索引号(或序号)

你可能感兴趣的:(C++ 多态理解)