C++多态性与虚函数表

C++多态的实现

多态分为静态多态和动态多态。静态多态是通过重载和模板技术实现,在编译的时候确定。动态多态通过虚函数和继承关系来实现,执行动态绑定,在运行的时候确定。动态多态实现有几个条件:
(1)多态分为静态多态和动态多态。静态多态是通过重载和模板技术实现的,在编译的时候确定。动态多态通过虚函数和继承关系来实现,执行动态绑定,在运行的时候确定。动态多态实现有几个条件:

  • 虚函数;
  • 一个基类的指针或引用指向派生类的对象;
    基类指针在调用成员函数(虚函数)时,就回去查找该对象的虚函数表。虚函数表的地址在每个对象的首地址。查找该虚函数表中该函数的指针进行调用。每个对象中保存的只是一个虚函数表的指针,c++内部为每一个类维持一个虚函数表,该类的对象都指向同一个虚函数表。虚函数表中为什么就能准确查找相应的函数指针呢?因为在类设计的时候,虚函数表直接从基类继承过来,如果覆盖了其中的某个虚函数,那么虚函数表的指针就会被替换,因此可以根据指针准确查找调用哪个函数。

虚函数的作用

  • 虚函数用于实现多态

  • 在这里插入图片描述
    用基类指针指向不同的派生类的对象时,基类指针调用其虚成员函数,则会调用其真正指向对象的成员函数,而不是基类中定义的成员函数(只要派生类改写了该成员函数)。若不是虚函数,则不管基类指针指向哪个派生类对象,调用时都会调用基类中定义的那个函数。
    本质:不是重载声明,而是覆盖。调用方式:通过基类指针或引用,执行时会根据指针指向对象的类,决定调用哪个函数。
    到这个地方还没完,其实完全可以不用父类类型的指针,直接创建子类对象来调用子类的普通函数也是可以的,为什么非要用虚函数呢?
    虽然这样说,但是实际开发中不是这样的,当我们使用一些类库、框架的时候,这些类库、框架时事先写好的。我们在使用的时候不能直接修改类库的源码,我们只能派生类库中的一些类来覆盖一些成员函数以实现我们的功能,但这些成员函数有的是由框架调用的。这种情况下,用虚函数是很好的办法。

  • 虚函数在设计上还具有封装和抽象的作用。比如抽象工厂模式。

虚函数的背景知识

1、用virtual关键字申明的函数叫做虚函数,虚函数肯定是类的成员函数。
2、存在虚函数的类都有一个一维的虚函数表叫做虚表。类的对象有一个指向虚表开始的虚指针。虚表是和类对应的,虚表指针是和对象对应的。
3、多态性是一个接口多种实现,是面向对象的核心。分为类的多态性和函数的多态性。
4、多态用虚函数来实现,结合动态绑定。
5、纯虚函数是虚函数再加上= 0。并且该函数只有声明,没有实现。
6、抽象类是指包括至少一个纯虚函数的类。

虚函数表是针对类的还是针对对象的?同一个类的两个对象的虚函数表示怎么维护的?

虚函数表示针对类的,编译器为每一个类维护一个虚函数表,虚函数表在编译的时候就确定了,每个对象的首地址保存着该虚函数表的指针,而类对象的虚函数指针vptr就是在运行阶段确定的,这是实现多态的关键。

纯虚函数如何定义,为什么对于存在虚函数的类中析构虚函数要定义成虚函数

为了实现多态进行动态绑定,将派生类对象指针绑定到基类指针上,对象销毁时,如果析构函数没有定义成虚析构函数,则会调用基类的析构函数,子类的数据没办法析构,造成内存泄露。如果要调用对象的析构函数,就需要将该对象的析构函数定义为虚函数,销毁时通过虚函数表找到对象的析构函数。

https://blog.csdn.net/JackZhang_123/article/details/80692420
http://eriol.iteye.com/blog/1167737

猜你喜欢

转载自blog.csdn.net/u014571489/article/details/84558138