写在前面

虚表指针
多继承下的虚表指针情况
override c++11

主要内容

为什么虚表当中虚函数按照其声明顺序放于表中?

同一个虚函数入口地址在父类虚表和子类虚表中的偏移量必须保持一致。
当多重继承的时候,子类必须把来自不同父类的虚函数,放入不同的虚表中,不然无法保持这些虚函数的偏移量和它们的父类一样。
1)虚函数按照其声明顺序放于表中。
2)父类的虚函数在子类的虚函数前面
因为虚函数的调用就是按照地址偏移,只有虚函数入口地址到这些相应的虚函数的偏移是一致的时候才能够使用同样的方式进行调用而不至于出错。C++的编译器应该是保证虚函数表的指针存在于对象实例中最前面的位置(这是为了保证取到虚函数表的有最高的性能——如果有多层继承或是多重继承的情况下)。 这意味着我们通过对象实例的地址得到这张虚函数表,然后就可以遍历其中函数指针,并调用相应的函数。

多继承的虚表情况是不是就有多个虚表指针?

多继承中会有多个虚函数表,几重继承就会有几个虚函数表。这些虚函数表会按照派生的顺序依次排列。如果子类改写了父类的虚函数,那么就会用子类自己的虚函数覆盖相应的父类虚函数;如果子类有新的虚函数,那么就添加到第一个虚函数表的末尾。也就是说会有多个虚表指针指向多个虚表。

虚表属于谁?

虚表属于类,每个类独有,父类和派生类的虚表不是共享的是独立的。构造函数会完成每个对象的虚表指针的初始化这个指针指向的是这个类共享的虚表空间。虚表是整个类共用的,他的大小取决于你定义的虚函数的个数,以及编译器的策略.一般存在于内存的某个地方,你不需要去管他。

为啥构造函数不能够是虚函数?

构造函数还没执行说明虚表指针还没有被初始化,还没虚表指针就没办法调用到构造函数所以两者矛盾就不能让构造函数作为虚函数。一般想要使用多态的基类会使得析构函数为下虚函数。因为析构函数的调用是这样的:派生类的析构函数一旦调用就会往上层调用父类的析构函数所以这不会影响对象的析构。

虚函数如果没有被覆盖重写

派生类直接继承父类的版本。
显示说明当前的虚函数是覆盖了父类的虚函数可以在参数列表的后面加上override关键字。
如果标记了某个函数但是该函数并没有覆盖已存在的虚函数此时编译器将报错。
合理的利用编译器为我们发现一些错误。

虚函数可以有默认参数么?

可以,但是虚函数调用的时候是按照静态类型决定的所以最好基类和派生类当中的默认实参最好一致。

虚析构函数

通过在基类当中将析构函数定义为虚函数以确保执行正确的析构函数版本。
只要基类的析构函数是虚函数,就能确保我们delete基类指针时将运行正确的析构函数版本。
如果基类的析构函数不是虚函数,则delete一个指向派生类的基类指针的时候将产生未定义的行为。
因为将调用的是基类的析构函数将不会调用派生类的析构函数如果派生类有资源将没办法释放。

析构函数分为两个部分:函数体和析构部分。
析构函数首先执行函数体,然后销毁成员,按照成员初始化顺序的逆序销毁,先构造的后析构。成员按照自己的类型调用自己的析构函数,基本数据类型啥也不用做。
析构函数隐式的析构部分负责销毁成员,除了销毁派生类自己的成员外还负责析构直接基类该直接基类负责自己的直接基类以此类推到继承链的顶端。
派生类的析构函数只负责销毁派生类自身分配的资源。 基类的析构函数会被自动的调用。