多态原理探究

1. 多态的目的

   我们不希望把对象看作是某一个特殊类型的成员,而是希望把它看作一个基本类型的成员。这样就允许我们编写不依赖于特殊类型的代码。

   这样就可以不必修改一般的处理函数,而只需要通过派生新的类型来达到程序拓展的目的。

   要达到这个目的,就需要根据实际的对象类型来判断重写函数的调用。

   a. 如果父类指针指向的是父类对象则调用父类中定义的函数。

   b. 如果父类指针指向的是子类对象则调用子类中定义的重写函数。

  多态原理探究

 

2. 如何产生多态?

   使用virtual声明的函数被重写后即可展现多态特性。多态使用的3个条件:

   a. 有继承

   b. 有virtual重写

   c. 有父类指针(引用)指向子类对象。 

 

3. C++编译器如何实现多态

   理论知识如下:

   a. 当类中声明虚函数时,编译器会在类中生成一个虚函数表vtable。

   b. 虚函数表是一个存储类成员函数指针的数据结构。

   c. 虚函数表是由编译器自动生成与维护的。

   d. virtual成员函数会被编译器放入虚函数表中。

   e. 当存在虚函数时,每个对象中都有一个指向虚函数表的指针,即vptr指针。C++编译器给父类对象、子类对象提前布局vptr指针。

      发生调用时,存在两种情况:

      1)func不是虚函数:编译器可直接确定被调用的成员函数

      2)func是虚函数:编译器根据对象的vptr指针,所指的虚函数表中查找func函数并调用,这里的查找和调用都在运行时完成(动态绑定)。

 

4. 动态绑定过程

   当编译器发现类中有虚函数的时候,编译器会创建一张虚函数表,把虚函数的函数入口地址放到虚函数表中,并且在类中增加一个指针:vptr,

   这个指针是指向对象的虚函数表。在多态调用的时候,根据vptr指针,找到虚函数表来实现动态绑定。

   注:在对象构建的时候,也就是在对象初始化调用构造函数的时候,编译器默认会在编写的每一个构造函数中,增加一些vptr初始化的代码。

       如果没有提供构造函数,编译器会提供默认的构造函数,会在默认构造函数中做这个工作,初始化vptr指针,使它指向本对象的虚函数表。

   子类继承基类的vptr指针,这个指针指向基类虚函数表,当子类调用构造函数时,子类的vpointer指针便会指向子类的虚函数表。

   多态原理探究

   通过虚函数表指针Vptr调用重写函数是在程序运行时进行的,编译器在编译的时候需要额外插入许多查找,判断的代码,运行时执行这些代码

   才能确定真正应该调用的函数。而普通成员函数是在编译时就确定了调用的函数。在效率上,虚函数的效率要低很多。

   出于效率考虑,没有必要将所有成员函数都声明为虚函数。

 

5. 构造函数和析构函数能不能是virtual的?

   构造函数不能用virtual修饰:我们知道多态是发生在对象已经建立的情况下,而构造函数调用时对象还没有建立,也就不存在多态。

   析构函数可以用virtual修饰:此时对象已经建立,我们希望在delete p(p为指向子类对象的基类指针)的时候能够调用子类自己的析构函数来释放资源。

 

 

原文链接: https://www.cnblogs.com/yanghh/p/12935373.html

欢迎关注

微信关注下方公众号,第一时间获取干货硬货;公众号内回复【pdf】免费获取数百本计算机经典书籍;

也有高质量的技术群,里面有嵌入式、搜广推等BAT大佬

    多态原理探究

原创文章受到原创版权保护。转载请注明出处:https://www.ccppcoding.com/archives/350241

非原创文章文中已经注明原地址,如有侵权,联系删除

关注公众号【高性能架构探索】,第一时间获取最新文章

转载文章受原作者版权保护。转载请注明原作者出处!

(0)
上一篇 2023年3月2日 上午6:10
下一篇 2023年3月2日 上午6:11

相关推荐