虚函数 纯虚函数 虚继承资料整理

来源:互联网 发布:软件添加广告sdk 编辑:程序博客网 时间:2024/06/16 00:51

感谢这些优秀的文章:

虚函数与纯虚函数
虚函数的实现1
虚函数的实现2
菱形继承与虚继承

虚函数

首先从虚函数开始说起吧.虚函数是实现了多态机制,具体表现为父类型的指针指向其子类的实例.然后通过服泪指针嗲用实际子类中的成员函数.这种技术可以让父类指针有多种形态.
如果调用非虚函数,无论对象是什么类型,都执行基类类型所定义的函数,非虚函数总是子啊编译时根据调用函数的对象,引用或指针类型而确定.
虚函数必须是基类的非静态成员函数。虚函数的作用是实现动态联编,也就是在程序的运行阶段动态地选择合适的成员函数,在定义了虚函数后,可以在基类的派生类中对虚函数重新定义,在派生类中重新定义的函数应与虚函数具有相同的形参个数和形参类型。以实现统一的接口,不同定义过程。如果在派生类中没有对虚函数重新定义,则它继承其基类的虚函数
函数只能借助于指针或者引用来达到多态的效果。

纯虚函数

是在基类中声明的虚函数,它在基类中没有定义,但要求任何派生类都要定义自己的实现方法。在基类中实现纯虚函数的方法是在函数原型后加“=0” virtualvoid GetName() =0
在很多情况下,基类本身生成对象是不合情理的。例如,动物作为一个基类可以派生出老虎、孔雀等子类,但动物本身生成对象明显不合常理。为了解决上述问题,将函数定义为纯虚函数,则编译器要求在派生类中必须予以重写以实现多态性。同时含有纯虚拟函数的类称为抽象类,它不能生成对象。这样就很好地解决了上述两个问题。
含有纯虚函数的泪称为抽象类
抽象类是一种特殊的类,它是为了抽象和设计的目的为建立的,它处于继承层次结构的较上层。
抽象类的定义: 称带有纯虚函数的类为抽象类。
抽象类的作用:抽象类的主要作用是将有关的操作作为结果接口组织在一个继承层次结构中,由它来为派生类提供一个公共的根,派生类将具体实现在其基类中作为接口的操作。所以派生类实际上刻画了一组子类的操作接口的通用语义,这些语义也传给子类,子类可以具体实现这些语义,也可以再将这些语义传给自己的子类。
使用抽象类时注意:抽象类只能作为基类来使用,其纯虚函数的实现由派生类给出。如果派生类中没有重新定义纯虚函数,而只是继承基类的纯虚函数,则这个派生类仍然还是一个抽象类。如果派生类中给出了基类纯虚函数的实现,则该派生类就不再是抽象类了,它是一个可以建立对象的具体的类。抽象类是不能定义对象的.

虚函数的实现(虚表)

虚函数可以做到动态绑定,为了实现动态绑定,编译器是通过一个表格(虚拟函数表),在运行时间接的调用实际上绑定的函数来达到动态绑定,其中这个我刚所说的表格其实现就是一个“虚拟函数表”。这张表对我们程序来说是透明的。是编译器为我们的代码自动加上去的(更准确的讲,并不是为所有的代码都添加一张虚拟函数表,而是只针对那些包括虚函数的代码才加上这张表的)。

既然有了这么一张虚拟函数表,自然而然我们就会想到,这个虚拟函数表里到底是存放一些什么东西呢?很简单,即然叫做虚拟函数表,当然是存放虚拟函数了,在c++中,该表每一行的元素应该就是我们代码中虚拟函数地址了,也就是一个指针。有了这个地址,我们可以调用实际代码中的虚拟函数了。

编译器既然为我们的代码加了一张虚拟函数表,那这张虚拟函数表怎么与我们的代码关联起来呢? 要实现动态绑定,我们应该利用这张虚拟函数表来调用虚拟函数,为了达到目的,编译器又会为我们的代码增加一个成员变量,这个成员变量就是一个指向该虚拟函数表的指针,该成员变量通常被命名为:vptr

当子类在改写了父类中的虚拟函数时,同时子类的vptr成员也会作修改此时,子类的vptr成员指向的虚拟函数表中的存放的虚拟函数指针不再是父类的虚拟函数地址了,而是子类所改写父类的虚拟函数地址。理解这一点就很容易想到了:原来多态体现在这里!

要想真正的搞明白要考虑这么几种继承模式 一般继承(无虚函数覆盖),一般继承(有虚函数覆盖),多重继承(无虚函数覆盖),多重继承(有虚函数覆盖)集中情况,我是参考的这篇文章

最后考虑一种棱形继承的情况,这样会发生调用歧义,但是虚继承可以解决这个问题.

原创粉丝点击